conatainer_of() macro in Linux Kernel -
When it comes to managing several data structures in code, you'll almost always need to embed one structure into another and retrieve them at any moment without being asked questions about memory offsets or boundaries. Let's say you have a struct person, as defined here:
struct person {
int age;
int salary;
char *name;
} p;
By only having a pointer on age or salary, you can retrieve the whole structure wrapping (containing) that pointer. As the name says, the container_of macro is used to find the container of the given field of a structure. The macro is defined in include/linux/kernel.h and looks like the following:
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
Don't be afraid of the pointers; just see them as follows:
container_of(pointer, container_type, container_field);
Here are the elements of the preceding code fragment:
- pointer: This is the pointer to the field in the structure
- container_type: This is the type of structure wrapping (containing) the pointer
- container_field: This is the name of the field to which
pointer points inside the structure
Let's consider the following container:
struct person {
int age;
int salary;
char *name;
};
Now, let's consider one of its instances, along with a pointer to the age member:
struct person somebody;
[...]
int *age_ptr = &somebody.age;
Along with a pointer to the name member (age_ptr),you can use the container_of macro in order to get a pointer to the whole structure (container) that wraps this member by using the following:
struct person *the_person;
the_person = container_of(age_ptr, struct person, age);
container_of takes the offset of age at the beginning of the struct into account to get the correct pointer location. If you subtract the offset of the field age from the pointer age_ptr, you will get the correct location. This is what the macro's last line does:
(type *)( (char *)__mptr - offsetof(type,member) );
Applying this to a real example, gives the following:
struct family {
struct person *father;
struct person *mother;
int number_of_sons;
int family_id;
} f;
/*
* Fill and initialise f somewhere */ [...]
/*
* pointer to a field of the structure
* (could be any (non-pointer) member in the structure)
*/
int *fam_id_ptr = &f.family_id;
struct family *fam_ptr;
/* now let us retrieve back its family */
fam_ptr = container_of(fam_id_ptr, struct family, family_id);
The container_of macro is mainly used in generic containers in the kernel.
That's all about container_of macro in kernel.