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...