在Linux中的list_entry

user/include/linux/list.h 

这个声明:

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

有人可以请解释这是什么,它是如何工作,预先感谢

PS请尽可能简化你的答案,我知道在Linux中的线程,进程,现在我正在探索可能性,我有点卡住了这个。

Solutions Collecting From Web of "在Linux中的list_entry"

考虑这样的两个结构:

 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转换为指向由ptr指向的struct container struct data值的struct container值的指针:

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

该宏通过计算struct containerdata_item的偏移量,并从data_ptr指针中减去许多字节来data_ptr 。 这个当被转换为struct container * ,会给出一个指向struct container的有效指针,该struct container包含这个特定的struct data “inside”。

这个宏也可以通过使用内建的offsetof()宏来简化一下:

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

在这里你可以找到这个解释:部分这是如何工作的?

这个宏用于查找给定其成员之一的结构的地址。

所以,举个例子,假设你有这样的结构:

 typedef struct { int i; int j; } typestruct; 

首先你需要知道的是宏的最后一部分:

  &((typestruct *)0)->j 

用来给出一个成员的偏移量。 因此,从内存转换为类型到成员的大小(以字节为单位)。 在这种情况下,它是sizeof(int) ,因为j只是在下面int i ; 所以我们假设这个表达式值为了简单起见。 你可以得到与宏相同的结果

 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 

你可以在这里学习更多,也可以在这个问题上学习 。

(括号是必要的,但被澄清)