Understanding container_of macro in the Linux kernel
Your usage example container_of(dev, struct wifi_device, dev);
might be a bit misleading as you are mixing two namespaces there.
While the first dev
in your example refers to the name of pointer the second dev
refers to the name of a structure member.
Most probably this mix up is provoking all that headache. In fact the member
parameter in your quote refers to the name given to that member in the container structure.
Taking this container for example:
struct container {
int some_other_data;
int this_data;
}
And a pointer int *my_ptr
to the this_data
member you'd use the macro to get a pointer to struct container *my_container
by using:
struct container *my_container;
my_container = container_of(my_ptr, struct container, this_data);
Taking the offset of this_data
to the beginning of the struct into account is essential to getting the correct pointer location.
Effectively you just have to subtract the offset of the member this_data
from your pointer my_ptr
to get the correct location.
That's exactly what the last line of the macro does.
The last sentence cast:
(type *)(...)
a pointer to a given type
. The pointer is calculated as offset from a given pointer dev
:
( (char *)__mptr - offsetof(type,member) )
When you use the cointainer_of
macro, you want to retrieve the structure that contains the pointer of a given field. For example:
struct numbers {
int one;
int two;
int three;
} n;
int *ptr = &n.two;
struct numbers *n_ptr;
n_ptr = container_of(ptr, struct numbers, two);
You have a pointer that points in the middle of a structure (and you know that is a pointer to the filed two
[the field name in the structure]), but you want to retrieve the entire structure (numbers
). So, you calculate the offset of the filed two
in the structure:
offsetof(type,member)
and subtract this offset from the given pointer. The result is the pointer to the start of the structure. Finally, you cast this pointer to the structure type to have a valid variable.
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.