Linux驱动编程 step-by-step (十) Linux 内核链表
終于可以清閑下來打理一下我的blog了,臺資企業(yè)真的事情很多很煩……
前幾篇文章對字符設(shè)備有個簡單介紹,并以簡單的一個字符設(shè)備驅(qū)動作結(jié)尾,其實(shí)linux上大部分驅(qū)動程序都是字符設(shè)備程序,Linux源碼中也可以看到很多的字符設(shè)備驅(qū)動,所以供學(xué)習(xí)的代碼還是很多的。
這一節(jié)本想說一下如何測試設(shè)備驅(qū)動,但是因?yàn)樽罱戳丝磧?nèi)核鏈標(biāo),所以稱還記的比較清楚趕緊記錄下來。有不到位的地方煩請指正。
Linux 內(nèi)核鏈表
鏈表的簡單介紹:
鏈表是線性表的實(shí)現(xiàn)方式之一,是一種常用的數(shù)據(jù)結(jié)構(gòu),用來組織一系列有序數(shù)據(jù),并通過指針將這些有序數(shù)列鏈成一條數(shù)據(jù)鏈。相對于數(shù)組來說,它有良好的伸縮性,可以動態(tài)的添加或者刪除等有點(diǎn)(但是訪問速度較數(shù)組慢)。
數(shù)據(jù)鏈表常有兩個域?數(shù)據(jù)域?與?指針域
內(nèi)核鏈標(biāo)是一個雙向循環(huán)鏈表,但是它與我們常用的鏈表有所不同.
常用的雙向鏈標(biāo)定義如下:
[cpp]?view plaincopy 這里的next 指針指向了下一個鏈標(biāo)節(jié)點(diǎn),通過node->data獲得鏈標(biāo)中的數(shù)據(jù), 類似下圖(但下圖有些不準(zhǔn)確)。
內(nèi)核鏈表結(jié)構(gòu)定義:
[cpp]?view plaincopy [cpp]?view plaincopy
在這里我們可以通過內(nèi)核鏈標(biāo)獲取獲取整個數(shù)據(jù)結(jié)構(gòu),并獲得有用數(shù)據(jù)。
這樣的好處是:實(shí)現(xiàn)了內(nèi)核鏈標(biāo)的通用性,不需要為每個結(jié)構(gòu)定義一個鏈表,使用統(tǒng)一的內(nèi)核鏈表即可。
那我們怎樣使用內(nèi)核鏈標(biāo)呢? 如何通過內(nèi)核鏈標(biāo)得到想要的數(shù)據(jù)結(jié)構(gòu)呢?
使用內(nèi)核鏈表:
定義包含內(nèi)核鏈標(biāo)的數(shù)據(jù)結(jié)構(gòu)
[cpp]?view plaincopy只要在數(shù)據(jù)結(jié)構(gòu)中包含struct list_head成員即可。
初始化內(nèi)核鏈表
使用內(nèi)核鏈標(biāo)需要一個鏈表頭,故需要先行初始化臉表頭
[cpp]?view plaincopy添加一個鏈表節(jié)點(diǎn)
[cpp]?view plaincopy它會將新的節(jié)點(diǎn)放于prev 與 next之間。
同樣可以調(diào)用list_add_tail, 在head之前添加一個鏈表節(jié)點(diǎn)。
刪除鏈表節(jié)點(diǎn):
[cpp]?view plaincopy這里即將 entry節(jié)點(diǎn)從鏈表中刪除(其實(shí)節(jié)點(diǎn)仍存在只是不在鏈表里邊了) [cpp]?view plaincopy
獲取數(shù)據(jù)結(jié)構(gòu)
[cpp]?view plaincopy定義 list_entry宏 來獲取數(shù)據(jù)結(jié)構(gòu),它會調(diào)用container_of 宏來獲取這個結(jié)構(gòu)體(container_of 宏我在前邊的文章里邊已經(jīng)闡述過)
ptr 填入鏈表節(jié)點(diǎn)指針, type填入數(shù)據(jù)結(jié)構(gòu)體類型, member示意鏈標(biāo)在結(jié)構(gòu)體中的名字。
如果現(xiàn)在我們知道鏈表的指針為entry,就可以這樣獲取整個結(jié)構(gòu)體。
以上是最基本的使用方法。
總結(jié)
以上是生活随笔為你收集整理的Linux驱动编程 step-by-step (十) Linux 内核链表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux驱动编程 step-by-st
- 下一篇: Linux驱动编程 step-by-st