开发者

list_entry in Linux

开发者 https://www.devze.com 2023-02-22 07:33 出处:网络
user/include/linux/list.h this declaration: #define list_entry(ptr, type, member) \\ ((type *)((char *)(ptr) – (unsigned long)(&((type *)0)->member)))
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, th开发者_如何学Pythonanks 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.


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 *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:

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".

The macro can also be simplified a bit by using the builtin offsetof() macro:

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


An explanation of this you find here: Section How Does This Work?


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 zero memory 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

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:

(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)

0

精彩评论

暂无评论...
验证码 换一张
取 消