макрос conatainer_of () у ядрі Linux -
Коли справа доходить до управління кількома структурами даних у коді, вам майже завжди потрібно буде вбудовувати одну структуру в іншу та отримувати їх у будь-який момент, не задаючи питань про зміщення пам’яті чи межі. Скажімо, у вас є структура людини, як визначено тут:
struct person {
int age;
int salary;
char *name;
} p;
Маючи лише вказівник на вік або зарплату, ви можете отримати всю структуру, яка обертає (містить) цей вказівник. Як випливає з назви, макрос container_of використовується для пошуку контейнера заданого поля структури. Макрос визначений у include / linux / kernel.h і виглядає так:
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
Не бійтеся покажчиків; просто перегляньте їх наступним чином:
container_of(pointer, container_type, container_field);
Ось елементи попереднього фрагмента коду:
- покажчик: це вказівник на поле в структурі
- container_type: Це тип обтікання структури (що містить) покажчик
- container_field: Це ім'я поля, на яке вказує вказівник всередині структури
Давайте розглянемо наступний контейнер:
struct person {
int age;
int salary;
char *name;
};
Тепер давайте розглянемо один із його випадків, разом із вказівником на віковий член:
struct person somebody;
[...]
int *age_ptr = &somebody.age;
Поряд з покажчиком на ім'я члена (age_ptr), ви можете використовувати макрос container_of, щоб отримати вказівник на всю структуру (контейнер), яка обертає цього члена, використовуючи наступне:
struct person *the_person;
the_person = container_of(age_ptr, struct person, age);
container_of враховує зміщення віку на початку структури, щоб отримати правильне розташування вказівника. Якщо відняти зміщення віку поля від покажчика age_ptr, ви отримаєте правильне розташування. Ось що робить останній рядок макросу:
(type *)( (char *)__mptr - offsetof(type,member) );
Застосовуючи це до реального прикладу, можна отримати наступне:
struct family {
struct person *father;
struct person *mother;
int number_of_sons;
int family_id;
} f;
[...]
int *fam_id_ptr = &f.family_id;
struct family *fam_ptr;
fam_ptr = container_of(fam_id_ptr, struct family, family_id);
Макрос container_of в основному використовується в загальних контейнерах ядра.
Це все про макрос container_of в ядрі.
rb_node
.