核心資料結構list head 常用函式解析

2021-06-03 00:57:00 字數 3225 閱讀 2778

list_for_each原型:

#define list_for_each(pos, head)\

for(pos = (head)->next,prefetch(pos->next); pos !=(head); \

pos= pos->next,prefetch(pos->next))

它實際上是乙個 for 迴圈,利用傳入的 pos 作為迴圈變數,從表頭 head 開始,逐項向後( next

方向)移動 pos ,直至又回到 head ( prefetch() 可以不考慮,用於預取以提高遍歷速度)。

注意:此巨集必要把list_head放在資料結構第一項成員,至此,它的位址也就是結構變數

的位址。

list_for_each_entry:

在linux核心原始碼中,經常要對鍊錶進行操作,其中乙個很重要的巨集是list_for_each_entry:

意思大體如下:

假設只有兩個結點,則第乙個member代表head,

list_for_each_entry的作用就是迴圈遍歷每乙個pos中的member子項。

圖1:

pos: 

pos:

___________ 

____________

| | 

|

| | 

|

........... 

| | 

................ 

|

| | 

|

| | 

|

member: 

___________> member |

|  | 

|

|

|

|  |

| |

|__________________|

巨集list_for_each_entry:

406#define list_for_each_entry(pos,head, member) 

\407 

for (pos =list_entry((head)->next, typeof(*pos),member); 

\408 

prefetch(pos->member.next),&pos->member !=(head); 

\409 

pos =list_entry(pos->member.next, typeof(*pos),member))

複製**

list_entry((head)->next, typeof(*pos),member)返回(head)->next物理指標所處位置向前減去offsetof()個位元組資料之後,其父變數pos的實體地址,父變數的型別在編譯時由typeof(*pos)自動返回.

所以list_for_each_entry遍歷head下面掛接的型別為typeof(*pos)的childs結構體們,當然每個child結構體包含struct list_headnode之類相似的雙向鍊錶list_head型別項,就這樣通過迴圈pos將依次指向雙向鍊錶上的各個child.(member就是child型別中被定義的變數名)

其中用到了函式list_entry():

這個函式的作用在圖1中表示就是可以通過已知的指向member子項的指標,獲得整個結構體的指標(位址)

334#define list_entry(ptr, type,member) \

335 

container_of(ptr,type, member)

複製**

和函式prefetch:

#define prefetch(x)__builtin_prefetch(x)

複製**

其中用到了builtin_prefetch:

prefetch的含義是告訴cpu那些元素有可能馬上就要用到,告訴cpu預取一下,這樣可以提高速度

其中用到了函式container_of():

493#define container_of(ptr, type,member) ()

其中又用到了offsetof()函式:

lxr上找到的原始碼:

#define offset_of(type, memb)\

47 ((unsignedlong)(&((type *)0)->memb))

offsetof(type, member)

該巨集在linux核心**(版本2.6.22)中定義如下:

#define offsetof(type, member) ((size_t) &((type*)0)->member); 

分析:(type *)0,將 0 強制轉換為 type 型指標,記 p = (type *)0,p是指向type的指標,它的值是0。那麼p->member 就是 member這個元素了,而&(p->member)就是menber的位址,而基位址為0,這樣就巧妙的轉化為了type中的偏移量。再把結果強制轉換為size_t型的就ok了,size_t其實也就是int。

typedef__kernel_size_t 

size_t;

typedef unsigned int __kernel_size_t; 

可見,該巨集的作用就是求出member在type中的偏移量

核心資料結構

關於開發驅動重要的核心資料結構,方便自己理解 driver object typedef struct driver object cshort type cshort size 乙個鍊錶,記錄了該驅動建立的所有裝置物件 pdevice object deiceobject ulong flags ...

核心資料結構

核心需要儲存i o元件使用的狀態資訊,可以通過若干核心資料結構比如說檔案開啟表等來完成 unix系統中在讀取乙個使用者檔案的時候,核心需要去檢查下快取,然後再去決定是否執行磁碟i o,在讀乙個程序映象時候,核心只需要從記憶體當中讀取資料,也就是說這些操作都可以呼叫read 函式來完成,但是語義不同 ...

核心資料結構

這部分包含了修改核心模組,所以要使用到核心鏈結表資料結構。首先你得定義乙個包含元素的結構去插入鍊錶。下邊這段 用c語言定義了生日結構 struct birthday 注意struct list head list。結構list head在包含目錄的裡有定義。它的作用就是嵌入包含列表節點的鏈結表。li...