Когда вы используете макрос container_of? - PullRequest
2 голосов
/ 28 февраля 2011

Я знаю, что делает макрос.

Во многих кодах уровня ядра он часто используется для обхода связанного списка.

Я хочу найти другие полезные случаи.
Когдаиспользуете ли вы container_of или CONTAINING_RECORD макрос?
Когда макрос чрезвычайно полезен?

Ответы [ 4 ]

7 голосов
/ 28 февраля 2011

container_of позволяет упростить ваши структуры данных, опуская указатели на родительские структуры.

Он используется в реализации связанного списка, так что узел списка может быть элементом любой структуры, и любой можетродительская структура без переноса явного указателя.

Другой пример - struct work_struct.Рабочая функция workqueue получает work_struct в качестве аргумента, и она имела общую полезную нагрузку «data».Это значение данных было удалено , что уменьшило структуру, так как рабочая функция может вызвать container_of, чтобы найти ее родительскую структуру.

5 голосов
/ 28 февраля 2011

Это способ обойти тот факт, что C не имеет универсальных шаблонов или шаблонов.

Вам нужен универсальный связанный список, поэтому вы просто помещаете указатели внутри самого узла (так что вы можете абстрагироватьудалите управление самой структурой), затем используйте CONTAINING_RECORD, чтобы найти остальные данные в вашем собственном коде, например:

struct Node { struct Node *prev, *next; }

//Now you can define functions that operate on a generic struct Node*

struct Item
{
    int myData;
    struct Node* node;  //this would point to the 'node' member of another Item
}

Теперь, учитывая struct Node, вы можете найти его Item, сказав:

CONTAINING_RECORD(ptr, Item, node)
4 голосов
/ 19 июля 2012

Для будущих поисков (ы): это лучшее объяснение, которое я нашел до сих пор:

http://psomas.wordpress.com/2009/07/01/weird-kernel-macros-container_of/

В основном (цитата):

"Теперь мы можем понять (хотя бы частично), что делает макрос. Он объявляет указатель на член структуры, на который указывает ptr, и назначает ему ptr. Теперь __mptr указывает на тот же адрес, что и ptrЗатем он получает смещение этого member в пределах struct и вычитает его из фактического адреса члена struct ‘instance’(ie __mptr). Приведение (char *)__mptr необходимо, так что «арифметика указателей» будет работать какнамеревался, то есть вычесть из __mptr ровно (size_t) байтов, которые offsetof «возвращает». "

, а также два других важных указания (цитата):

"Я действительно не могу понять, почему мы не можем использовать указатель ptr напрямую. Мы можем пропустить первую строку, и макрос может быть

#define container_of(ptr, type, member) (type *)( (char *)(ptr) - offsetof(type,member) )

ptr используется только один раз - мы неНе нужно беспокоиться о побочных эффектах. Может быть, это просто хорошая практика кодирования. "

и тон позже отредактировал оригинальное сообщение (цитируется):

«По-видимому, первая строка предназначена для« проверки типов ».Это гарантирует, что type имеет член с именем member (однако, я думаю, это также делается с помощью макроса offsetof), и если ptr не является указателем на правильный тип (тип * 1034)*), компилятор выведет предупреждение, которое может быть полезно для отладки. "

0 голосов
/ 28 февраля 2011

Он корректирует указатель на член структуры на указатель на содержащую структуру; это используется различными способами в ядре, наиболее распространенный может быть описан как понижающий со статическим смещением, где внешняя структура извлекается (путем включения) из внутреннего, и вызывающая сторона вызывает метод для внутреннего объекта, который затем отправляется методу внешнего объекта.

Хорошо, что без поддержки OO от компилятора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...