Linux 中的 list_entry
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5550404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
list_entry in Linux
提问by likeIT
user/include/linux/list.h
this declaration:
本声明:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – (unsigned long)(&((type *)0)->member)))
can somebody please explain what is this and how does it work, thanks in advance
有人可以解释一下这是什么以及它是如何工作的,在此先感谢
P.S. please simplify your answer as much as possible, I know about threads, processes in Linux, now I'm exploring possibilities and I'm a little bit stuck with this one.
PS,请尽可能简化您的答案,我了解 Linux 中的线程和进程,现在我正在探索各种可能性,但我对这个问题有点困惑。
采纳答案by Petri Lehtinen
Consider two structs like this:
考虑两个这样的结构:
struct data {
int something;
};
struct container {
int something_before;
struct data data_item;
int something_after;
};
Assume you have a pointer to a struct data
value:
假设您有一个指向struct data
值的指针:
struct data *data_ptr;
The list_entry()
macro helps you to convert data_ptr
to a pointer to the struct container
value that holds the struct data
value, pointed to by ptr
:
该list_entry()
宏可帮助您转换data_ptr
为指向struct container
保存该struct data
值的值的指针,指向ptr
:
struct container *cont_ptr = list_entry(data_ptr, struct container, data_item);
The macro works by computing the offset of data_item
inside the struct container
, and subtracting that many bytes from the data_ptr
pointer. This, when cast to struct container *
, gives a valid pointer to the struct container
that holds this particular struct data
"inside".
宏的工作原理是计算data_item
内部的偏移量struct container
,然后从data_ptr
指针中减去那么多字节。This,当转换为 时struct container *
,会给出一个有效的指针,指向struct container
包含此特定struct data
“内部”的 。
The macro can also be simplified a bit by using the builtin offsetof()
macro:
宏也可以通过使用内置offsetof()
宏来简化一点:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – offsetof(type, member)))
回答by stacker
An explanation of this you find here: Section How Does This Work?
回答by Dr Beco
This macro is used to find the address of a struct given one of its member.
该宏用于在给定其成员之一的情况下查找结构的地址。
So, for example, suppose you have the struct:
因此,例如,假设您有以下结构:
typedef struct
{
int i;
int j;
} typestruct;
First thing you need to know is that the last part of the macro:
您需要知道的第一件事是宏的最后一部分:
&((typestruct *)0)->j
Is used to give the offset of a member. So, it is the size, in bytes, from the zeromemory casted to the type, to the member. In this case, it is the sizeof(int)
, because j
is just bellow int i
; So lets assume this expression values 4
for simplicity. You can get the same result with the macro
用于给出成员的偏移量。因此,它是从零内存转换为类型到成员的大小(以字节为单位)。在这种情况下,它是sizeof(int)
,因为j
就在下面int i
;所以4
为了简单起见,让我们假设这个表达式值。您可以使用宏获得相同的结果
offsetof(typestruct, j);
Now we want to calculate the address of temp
, where temp
is typestruct temp
. To do that, we simple compute the address of the pointer minus the member position. The address of the pointer is:
现在我们要计算 的地址temp
,其中temp
是typestruct temp
。为此,我们简单地计算指针的地址减去成员位置。指针地址为:
(typestruct *)((char *) &temp.j)
Hence, the subtraction is:
因此,减法是:
&temp == (typestruct *)((char *) &temp.j) - offsetof(typestruct, j)
or, like the macro says:
或者,就像宏说的:
&temp == (typestruct *)((char *) &temp.j) - &((typestruct *)0)->j
You can learn much more here, and also in this question.
(Parenthesis are necessary, but was eliminated for clarification)
(括号是必要的,但为了澄清而被删除)