2011-04-05 26 views
23
user/include/linux/list.h 

此聲明:LIST_ENTRY在Linux中

#define list_entry(ptr, type, member) \ 
((type *)((char *)(ptr) – (unsigned long)(&((type *)0)->member))) 

可有人請解釋這是什麼,它是如何提前

P.S.工作,謝謝請儘可能簡化您的答案,我知道Linux中的線程和進程,現在我正在探索可能性,並且我對此有點卡住了。

+0

如今[LIST_ENTRY](http://lxr.free-electrons.com/ident?i=list_entry)宏[定義](HTTP ://lxr.free-electrons.com/source/include/linux/list.h)作爲[container_of](http://lxr.free-electrons.com/ident?i=container_of)宏(這幾乎是相同的到您發佈的舊'list_entry'版本),[Radek Pazdera](https://github.com/pazdera)在[他的博客]上對其進行了很好的解釋(http://radek.io/2012/11/10/神奇-container_of宏/)。據我所知,這個改變是在內核版本[2.4.37](http://lxr.free-electrons.com/source/include/linux/list.h?v=2.4.37)和'2.6之間進行的。 11'。 – 2016-02-19 18:33:26

回答

27

考慮兩個結構是這樣的:

struct data { 
    int something; 
}; 

struct container { 
    int something_before; 
    struct data data_item; 
    int something_after; 
}; 

假設你有一個指向struct data值:

struct data *data_ptr; 

list_entry()宏可以幫助您將data_ptr轉換爲指向struct container值的指針,該值保存通過計算struct container內的偏移的data_item,並減去從data_ptr指針很多字節

struct container *cont_ptr = list_entry(data_ptr, struct container, data_item); 

宏作品:值,指向ptr。當投射到struct container *時,它給出了一個指向struct container的有效指針,該指針持有這個特定的struct data「inside」。

宏也可以通過使用內置offsetof()宏被簡化了一下:

#define list_entry(ptr, type, member) \ 
    ((type *)((char *)(ptr) – offsetof(type, member))) 
+0

精彩解說! – kumar 2012-03-16 10:08:58

+0

編譯時在「 - 」(短劃線)上給出錯誤。將短劃線更改爲「 - 」(減號)。 – Jossi 2016-04-20 21:40:57

2

該宏用於查找給定它的部件中的一個的結構的地址。

因此,舉例來說,假設你有結構:

​​

你需要知道的第一件事是,宏的最後一部分:

&((typestruct *)0)->j 

是用來給補償的成員。因此,它是從內存轉換爲類型到成員的大小(以字節爲單位)。在這種情況下,它是sizeof(int),因爲j只是低於int i;因此,爲了簡單起見,我們假設這個表達式值爲4。您可以與宏

offsetof(typestruct, j); 

現在我們要計算的temp地址,其中temptypestruct temp得到同樣的結果。爲此,我們簡單地計算指針的地址減去成員位置。指針的地址是:

(typestruct *)((char *) &temp.j) 

因此,減法是:

&temp == (typestruct *)((char *) &temp.j) - offsetof(typestruct, j) 

,或者像宏說:

&temp == (typestruct *)((char *) &temp.j) - &((typestruct *)0)->j 

你可以學到更多的here,也在這question

(括號是必要的,但被淘汰澄清)