|
|
|
|
-------------------------------------------------------------------------------------------------- /** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -------------------------------------------------------------------------------------------------- 指針ptr指向結構體type中的成員member;通過指針ptr,返回結構體type的起始地址,如圖2。
type |----------| | | | | |----------| ptr--> | member --| |----------| | | | | |----------| 圖2 list_entry()宏的示意圖 爲了便於理解,在此給予進一步說明。 例如my_list結構: struct my_list{ void *mydata; struct list_head list; }; struct list_head *pos; 則list_entry(pos, mylist, list)宏,就可以根據pos的值,獲取mylist的地址,也就是指向mylist的指針,這樣,我們就可以存取mylist->mydata字段了。 可爲什麼能夠達到這樣的效果? list_entry(pos, mylist, list) 展開以後爲: ((struct my_list *)((char *)(pos) - (unsigned long)(&((struct my_list *)0)->list))) 這看起來會使大多數人眩暈,但仔細分析一下,實際很簡單。 ((size_t) &(type *)0)->member)把0地址轉化爲type結構的指針,然後獲取該結構中member成員的指針,並將其強制轉換爲size_t類型。於是,由於結構從0地址開始定義,因此,這樣求出member的成員地址,實際上就是它在結構中的偏移量。 |
|
內核鏈表list_entry()宏詳解
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.