C語言分層模式實現

2021-07-25 11:47:42 字數 4879 閱讀 5353

今天給大家帶來微控制器、嵌入式中比較常用的一種程式設計方法--分層設計模式,核心中就大量採用這種設計方式,一般對於某種硬體體系分為幾層,以乙個核心層來管理,它會抽象出硬體或者個體的共性操作來進行管理,很像在用c語言實現物件導向的設計。

下面就以實際**來簡單說明。假設我們有這麼一種需求,需要從某些裝置讀取一些資料,但是這些裝置可能有51體系的,也可能有arm體系的。那麼我們應該抽象乙個資料結構來表示這種這些傳送資料的裝置。這就是核心層需要做的工作,假如我們裝置有兩個共性:

1.使用前需要初始化

2.能收到資料

那麼我們的資料結構就應該這麼抽象:

struct receiveopr

int (*getdevdata)(char data); //裝置接收資料的函式

int (*devinit)(); //裝置初始化函式

但是核心層管理的不僅僅是乙個裝置,為了方便核心層能找到某個裝置,那麼就需要給裝置乙個標示,這個標示可以有很多種,比如裝置名字,產品id等等,這裡我們以裝置名來區分。所以上面結構體就應該繼續新增名字成員,變為:

struct receiveopr

char *name; //接收裝置的名字

int (*getdevdata)(char data); //裝置接收資料的函式

int (*devinit)(); //裝置初始化函式

那麼核心層如何管理這些裝置呢?比較簡單也是比較常見的就是裝置鍊錶了,也就是我們普通的資料結構鍊錶,所以還需要乙個指標,來操作這個裝置鍊錶,於是,結構體應該再新增乙個成員,變為:

struct receiveopr

char *name; //接收裝置的名字

int (*getdevdata)(char data); //裝置接收資料的函式

int (*devinit)(); //裝置初始化函式

struct receiveopr *next; //用來管理鍊錶

核心中有種雙向鍊錶的資料結構 list_head,它提供了更為強大的鍊錶管理能力,是核心最核心的資料結構之一,有興趣也可以移植那個來用。到這裡,我們的接收裝置的功能抽象就基本完成了(如果在實現過程中發現還需要其他成員,可以隨時新增)。

那麼核心層如何具體去實現呢?貼一下**通過注釋就能明白。

receive_manager.h---輸入裝置核心層標頭檔案

#ifndef _receive_manager_h

#define _receive_manager_h

struct receiveopr

char *name; //接收裝置的名字

int (*getdevdata)(char data); //裝置接收資料的函式

int (*devinit)(); //裝置初始化函式

struct receiveopr *next; //用來管理鍊錶

//函式宣告

int registerrecvopr(struct receiveopr *p);

int selectrecvdev(char *name);

int getdevdata(char data);

int recvdevinit();

int recvmanagerinit();

#endif /* _receive_manager_h */

receive_manager.c---輸入裝置核心層實現檔案

#include

#include

#include

static struct receiveopr *listreceivehead = null; //裝置鍊錶的煉表頭

static struct receiveopr *defaultdev = null; //需要操作的裝置指標

* @brief 核心層提供給具體裝置的註冊函式,每個裝置都要提供上面的結構體指標,然後註冊到核心層

* @param p **行數

int registerrecvopr(struct receiveopr *p)

struct receiveopr *listtmp;

if (!listreceivehead)

listreceivehead = p;

p->next = null;

else

listtmp = listreceivehead;

while (listtmp->next)

listtmp = listtmp->next;

listtmp->next = p;

p->next = null;

return 0;

* @brief 根據name在鍊錶中找到相應的裝置,然後賦給指標 defaultdev

* @param name 裝置名字

int selectrecvdev(char *name)

struct receiveopr *listtmp = listreceivehead;

while (listtmp)

if (strcmp(listtmp->name, name) == 0)

defaultdev = listtmp;

return 0;

listtmp++;

return -1;

* @brief 根據指定的defaultdev,取出其中的資料,存到data陣列中

* @param data 陣列指標

int getdevdata(char data)

int ret;

if(defaultdev)

ret = defaultdev->getdevdata(data);

return ret;

else

return -1;

* @brief 根據指定的defaultdev,對其進行初始化

int recvdevinit()

if(defaultdev)

if(defaultdev->devinit() == 0)

return 0;

else

return -1;

else

return -1;

* @brief 對需要管理的裝置進行註冊,後邊會說到

int recvmanagerinit()

registerarmrecv();

return 0;

核心層簡單的管理工作就完成了,總結下就是:

1.提供 registerrecvopr 介面給具體裝置用,並把裝置新增到裝置鍊錶

2.提供 recvdevinit、selectrecvdev、getdevdata介面給上層用,來選擇裝置並使用裝置

那麼我們具體的裝置要怎麼做呢,就是實現核心層定義的結構體,然後註冊到核心層即可,下面以乙個模擬裝置來說明

arm_recv.c---假設這是arm體系下乙個裝置,功能沒有實現,只是模擬用

#include

static char buf[16];

static int fd;

static int getarmrecvdev(char data);

static int armrecvinit();

//這是核心層提供的裝置抽象,具體裝置檔案就是需要去挨個實現這些成員

static struct receiveopr armrecvdev = {

.name = "arm_recv",

.getdevdata = getarmrecvdev,

.devinit = armrecvinit,

//提交資料的函式,只是模擬而已

static int getarmrecvdev(char data)

int i, j=0;

int ret;

ret = read(fd, buf, 16);

if(ret > 0)

for(i=0; i<16; i++)

if(i%2 == 0)

data[j] = buf[i];

j++;

return (ret / 2);

else

return -1;

//裝置初始化函式

static int armrecvinit()

fd = open("/dev/power", o_rdwr);

if (fd < 0)

printf("can't open arm_recv!\n");

return -1;

else

printf("open arm_recv success!\n");

return 0;

//註冊函式,核心層初始化時候會依次呼叫各個裝置的註冊函式

int registerarmrecv(void)

return registerrecvopr(&armrecvdev);

這裡只是舉了乙個例子,具體的裝置功能當然要複雜的多,假如還有個51體系的,或者stm32的,那麼完全可以再實現兩個檔案:51recv.c和stm32.c來註冊

到核心層。

最後,來看下上層如何通過核心層來操作具體裝置

main.c---使用例項

#include "receive_manager.h"

int main(int argc, char **argv)

int ret;

char buf[8];

recvmanagerinit(); //註冊各個輸入裝置

selectrecvdev("arm_recv"); //選擇要操作的裝置

recvdevinit(); //對選擇的裝置進行初始化

while(1)

ret = getdevdata(buf); //操作裝置

printf("%d\n", ret);

簡單吧,這樣的設計使我們的程式層次感更加明了,方便管理我們的專案。這裡只是簡單的做了介紹,實際專案中使用的核心層管理要複雜的多。

C語言模式實現C 繼承和多型

這個問題主要考察的是c和c 的區別,以及c 中繼承和多型的概念。c和c 的區別 c語言是面向過程的語言,而c 是物件導向的過程。什麼是物件導向和面向過程?面向過程就是分析解決問題的步驟,然後用函式把這些步驟一步一步的進行實現,在使用的時候進行一一呼叫就行了,注重的是對於過程的分析。物件導向則是把構成...

C語言模式實現C 繼承和多型

c實現乙個struct a和struct b各包含乙個int成員a和b,要求達到b繼承了a的效果,也就是b裡面包含乙個a。並且能達到多型的效果,也就是乙個a p指向a調的是a的函式,指向b呼叫的是b的函式。1.繼承 1 c 的繼承 在c 中,可以用乙個類 子類 去繼承另乙個類 父類 子類可以得到父類...

PHP 分層模式和mvc模式

繼續昨天沒完的內容,分層開發模式。分層開發模式分析 可讀性 維護性 擴充套件性相比model1模式有了明顯改善,但是也有不足。有些頁面既充當了介面,同時又去響應使用者的各種請求,當請求過多時,頁面的結構遭到破壞,也就是說 比較亂。mvc m模型model v檢視view c控制器ctrl 它是個軟體...