Подтвердить что ты не робот

List_entry в Linux

user/include/linux/list.h

это объявление:

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

может кто-нибудь объяснить, что это такое и как он работает, заранее спасибо

P.S. пожалуйста, упростите свой ответ в максимально возможной степени, я знаю о потоках, процессах в Linux, теперь я изучаю возможности, и я немного застрял с этим.

4b9b3361

Ответ 1

Рассмотрим две такие структуры:

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 data, на которое указывает ptr:

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

Макрос работает, вычисляя смещение data_item внутри struct container и вычитая, что много байтов указателя data_ptr. Это при приведении к struct container * дает действительный указатель на struct container, который содержит этот конкретный struct data "внутри".

Макрос можно также немного упростить, используя встроенный макрос offsetof():

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

Ответ 3

Этот макрос используется для нахождения адреса структуры, заданной одним из его членов.

Итак, предположим, что у вас есть struct:

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

Прежде всего вам нужно знать, что последняя часть макроса:

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

Вы можете узнать гораздо больше здесь, а также в этом question.

(Скобки необходимы, но устранены для пояснения)