當(dāng)前位置:首頁(yè) > 學(xué)習(xí)資源 > 講師博文 > Linux內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)的一點(diǎn)認(rèn)識(shí)
Linux內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)的一點(diǎn)認(rèn)識(shí)
時(shí)間:2018-10-28 來(lái)源:華清遠(yuǎn)見(jiàn)
大家都知道linux內(nèi)核是世界上優(yōu)秀的軟件之一,作為一款優(yōu)秀的軟件,其中的許多的設(shè)計(jì)都精妙之處,十分值得學(xué)習(xí)和借鑒。今天我們就帶大家看一下內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)中一點(diǎn)設(shè)計(jì)。
打開(kāi)內(nèi)核源碼中的 include/linux/list.h頭文件,就可以看到內(nèi)核中聲明的一些與鏈表操作相關(guān)的結(jié)構(gòu)體定義和函數(shù)接口。內(nèi)核中使用更多的是雙向循環(huán)鏈表。我們就看一看內(nèi)核中雙向循環(huán)鏈表的精妙之處吧。
首先看鏈表節(jié)點(diǎn)的結(jié)構(gòu)體的定義:
struct list_head{
struct list_head *next, *prev;
};
大家都可以看到,該結(jié)構(gòu)體的成員僅包含了兩個(gè)指向前和后的兩個(gè)結(jié)構(gòu)體指針,但是在該結(jié)構(gòu)體中卻沒(méi)有數(shù)據(jù)成員,那么到時(shí)候鏈表中沒(méi)有任何數(shù)據(jù),這樣的鏈表有什么用呢?其實(shí)這就是內(nèi)核鏈表設(shè)計(jì)的巧妙之處,因?yàn)樵谡麄(gè)內(nèi)核中需要使用鏈表來(lái)存放的數(shù)據(jù)類型太多了,因此如果將內(nèi)核的數(shù)據(jù)結(jié)構(gòu)定義成固定的話,就會(huì)增加大量的結(jié)構(gòu)體類型的定義,而內(nèi)核將數(shù)據(jù)成員的定義變的靈活了,就是當(dāng)用到什么樣的數(shù)據(jù)時(shí)就臨時(shí)添加什么數(shù)據(jù),那到底是怎么做的呢?再看下邊的一個(gè)結(jié)構(gòu)體的定義:
struct Data{
int a;
struct list_head p;
};
其中成員a是我們的數(shù)據(jù),而鏈表節(jié)點(diǎn)的變量變成了我們新結(jié)構(gòu)體類型的成員。這樣定義的話,只需要將其中的成員p添加到一個(gè)雙向循環(huán)鏈表中,通過(guò)成員p我們就可以得到我們的數(shù)據(jù)成員a。可以這樣比喻,就是成員p就是一個(gè)晾衣架,有很多晾衣架都掛在一個(gè)晾衣桿上,但是每個(gè)晾衣架上掛什么衣服就比較隨便了。只要我們找到一個(gè)晾衣架就可以立刻得到掛在上邊的衣服了。
下邊提供一個(gè)示例代碼,闡釋一下這中用法:
struct list_head{
struct list_head *next, *prev;
};
/* data struct */
struct Data{
int a;
struct list_head p;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
#define mycontainer_of(memadd, type, memname) \
((struct type*)(((char*)memadd - ((unsigned long)&(((struct type*)0)->memname)))))
void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
int main(void)
{
//初始化雙向鏈表頭
struct list_head *head = malloc(sizeof(struct list_head));
INIT_LIST_HEAD(head);
struct list_head *q;
//初始化數(shù)據(jù)結(jié)構(gòu)體的值
struct Data data[4] = {0};
int i;
for ( i = 0; i < 4; i++)
{
data[i].a = i + 1;
}
//將數(shù)據(jù)結(jié)構(gòu)體中的list_head類型成員頭插入到雙向鏈表中
for(i = 0; i < 4; i++)
{
list_add(&(data[i].p), head);
}
//根據(jù)結(jié)構(gòu)體的一個(gè)成員地址進(jìn)而找到整個(gè)結(jié)構(gòu)體的地址
for (q = head->next; q != head; q = q->next )
{
struct Data *temp;
temp = mycontainer_of(q, Data, p);
printf("%d\n", temp->a);
}
return 0;
}
課程分享:華清遠(yuǎn)見(jiàn)聯(lián)合NXP推出i.MX8M Plus開(kāi)發(fā)與實(shí)踐
課程分享:鴻蒙HarmonyOS系統(tǒng)及物聯(lián)網(wǎng)開(kāi)發(fā)實(shí)戰(zhàn)課程(
課程分享:HaaS EDU K1開(kāi)發(fā)教程(附課程視頻及源碼下
新版C語(yǔ)言編程之控制語(yǔ)句視頻教程重磅贈(zèng)送(嵌入式入
價(jià)值2000元的嵌入式精裝教程大禮包免費(fèi)送!(搞懂嵌入
價(jià)值1000元的最新ARM系列視頻完整版教程新鮮出爐(免
【最新】ARM課程課堂實(shí)錄精華版視頻免費(fèi)領(lǐng)取(內(nèi)含源
如何利用機(jī)器學(xué)習(xí)構(gòu)建個(gè)性化推薦系統(tǒng)
嵌入式系統(tǒng)從上電到操作系統(tǒng)運(yùn)行的完整啟動(dòng)流程
如何在不同工作場(chǎng)景下優(yōu)化嵌入式系統(tǒng)的電源消耗
硬件抽象層(HAL)的設(shè)計(jì)如何提高代碼的可移植性
批量歸一化在深度學(xué)習(xí)訓(xùn)練中的作用和實(shí)現(xiàn)方法
物聯(lián)網(wǎng)項(xiàng)目中設(shè)計(jì)嵌入式系統(tǒng)時(shí)的關(guān)鍵技術(shù)和考慮因素
通過(guò)自然語(yǔ)言處理技術(shù)理解文本的深層含義
如何基于RISC-V架構(gòu)設(shè)計(jì)高效能的嵌入式系統(tǒng)
LSTM和GRU在時(shí)間序列預(yù)測(cè)中的應(yīng)用
JTAG和SWD的調(diào)試技術(shù)及應(yīng)用
