user/include/linux/list.h
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – (unsigned long)(&((type *)0)->member)))
可有人請解釋這是什麼,它是如何提前
P.S.工作,謝謝請儘可能簡化您的答案,我知道Linux中的線程和進程,現在我正在探索可能性,並且我對此有點卡住了。
user/include/linux/list.h
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – (unsigned long)(&((type *)0)->member)))
可有人請解釋這是什麼,它是如何提前
P.S.工作,謝謝請儘可能簡化您的答案,我知道Linux中的線程和進程,現在我正在探索可能性,並且我對此有點卡住了。
考慮兩個結構是這樣的:
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)))
該宏用於查找給定它的部件中的一個的結構的地址。
因此,舉例來說,假設你有結構:
你需要知道的第一件事是,宏的最後一部分:
&((typestruct *)0)->j
是用來給補償的成員。因此,它是從內存轉換爲類型到成員的大小(以字節爲單位)。在這種情況下,它是sizeof(int)
,因爲j
只是低於int i
;因此,爲了簡單起見,我們假設這個表達式值爲4
。您可以與宏
offsetof(typestruct, j);
現在我們要計算的temp
地址,其中temp
是typestruct temp
得到同樣的結果。爲此,我們簡單地計算指針的地址減去成員位置。指針的地址是:
(typestruct *)((char *) &temp.j)
因此,減法是:
&temp == (typestruct *)((char *) &temp.j) - offsetof(typestruct, j)
,或者像宏說:
&temp == (typestruct *)((char *) &temp.j) - &((typestruct *)0)->j
(括號是必要的,但被淘汰澄清)
如今[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