2015-03-16 7 views
1

Ниже код из ядра Linux:Что означает эта часть кода в kernel.h?

/** 
639 * container_of - cast a member of a structure out to the containing structure 
640 * @ptr: the pointer to the member. 
641 * @type: the type of the container struct this is embedded in. 
642 * @member: the name of the member within the struct. 
643 * 
644 */ 
645 #define container_of(ptr, type, member) ({   \ 
646  const typeof(((type *)0)->member) *__mptr = (ptr); \ 
647  (type *)((char *)__mptr - offsetof(type,member));}) 
648 

Я не понимаю, что он делает на линии 646-648. Я знаю, что эти две строки делают из комментариев над ним, но я не понимаю код слово за словом. Вы можете мне это объяснить?

+0

Главный трюк заключается в том, что этот код будет запущен в [время компиляции] (https://en.wikipedia.org/wiki/Compile_time). Конечно, в [время выполнения] (https://en.wikipedia.org/wiki/Run_time_%28program_lifecycle_phase%29) это приведет к разыменованию указателя NULL, как вы можете видеть в коде '((type *) 0) - > member'. Но компилятор умный и понимает, что этот код можно вычислить во время компиляции, поэтому не будет разыменоваться указатель NULL. Этот код просто вычисляет смещение (в байтах) члена структуры ('member') в самой структуре (' type'), а затем возвращает структуру, содержащую этот член. –

+1

[Здесь] (http://www.kroah.com/log/linux/container_of.html) отличное объяснение о 'container_of' Грега Кроа-Хартмана. –

+0

Привет, спасибо @SamProtsenko. Есть ли место, где объясняются макросы ядра? Не могли бы вы сообщить мне сайт или ссылку? – theCuriousOne

ответ

0

Цель состоит в том, что с учетом анонимного указателя, который, как вы знаете, на самом деле является указателем на какой-либо элемент большей структуры, вычисляет начальный адрес этой более крупной структуры.

0

646 -> Сначала создайте указатель (__mptr) для члена. Сначала создается нулевой указатель. Это необходимо для поиска типа элемента (тип члена не указан в качестве аргумента!).

647 -> Нарисовать созданный указатель (__mptr) на char *. Затем найдите смещение этого члена, используя определение «offsetof». Затем вычтите смещение от залитого __mptr. Бросок должен выполняться, потому что результат, заданный offsetof, находится в байтах. В противном случае начало контейнера неправильно вычисляется (вычисление с указателями основано на типе указателя) Необходим дополнительный приведение к типу * в строке 647, потому что нужно вернуть правильный тип указателя.

Смежные вопросы