When I was browsing the Linux kernel, I found a container_of macro which is defined as follows:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
I understand what does container_of do, but what I do not understand is the last sentence, which is
(type *)( (char *)__mptr - offsetof(type,member) );})
If we use the macro as follows:
container_of(dev, struct wifi_device, dev);
The corresponding part of the last sentence would be:
(struct wifi_device *)( (char *)__mptr - offset(struct wifi_device, dev);
which looks like doing nothing.
Could anybody please fill the void here?
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.
It is an utilisation of a gcc extension, the statements expressions. If you see the macro as something returning a value, then the last line would be :
return (struct wifi_device *)( (char *)__mptr - offset(struct wifi_device, dev);
See the linked page for an explanation of compound statements. Here is an example :
int main(int argc, char**argv)
{
int b;
b = 5;
b = ({int a;
a = b*b;
a;});
printf("b %d\n", b);
}
The output is
b 25
Very useful link for understanding container_of macro in linux kernel.
https://linux-concepts.blogspot.com/2018/01/understanding-containerof-macro-in.html
A little real context says clearer, below use red-black tree as example, which is the
way that I understand container_of.
as Documentation/rbtree.txt states, in linux kernel code, it's not rb_node contain data
entry, rather
Data nodes in an rbtree tree are structures containing a struct
rb_node member.
struct vm_area_struct (in file include/linux/mm_types.h:284) is such a structure,
in the same
file, there is a macro rb_entry which is defined as
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
clearly, rb_entry is same as container_of.
at mm/mmap.c:299 inside function definition browse_rb, there is a usage of rb_entry:
static int browse_rb(struct mm_struct *mm)
{
/* two line code not matter */
struct rb_node *nd, *pn = NULL; /*nd, first arg, i.e. ptr. */
unsigned long prev = 0, pend = 0;
for (nd = rb_first(root); nd; nd = rb_next(nd)) {
struct vm_area_struct *vma;
vma = rb_entry(nd, struct vm_area_struct, vm_rb);
/* -- usage of rb_entry (equivalent to container_of) */
/* more code not matter here */
now it is clear, in container_of(ptr, type, member),
type is the container struct, here struct vm_area_struct
member is name of a member of type instance, here vm_rb, which is of type rb_node,
ptr is a pointer pointing member of an type instance, here rb_node *nd.
what container_of do is, as in this example,
given address of obj.member (here obj.vm_rb), return the
address of obj.
since a struct is a block of contiguous memory, address of obj.vm_rb minus
offset between the struct and member will be the container's address.
include/linux/kernel.h:858 -- definition of container_of
include/linux/rbtree.h:51 -- definition of rb_entry
mm/mmap.c:299 -- usage of rb_entry
include/linux/mm_types.h:284 -- struct vm_area_struct
Documentation/rbtree.txt: -- Documentation of red-black tree
include/linux/rbtree.h:36 -- definition of struct rb_node
P.S.
Above files are in current develop version, i.e, 4.13.0-rc7.
file:k mean kth line in file.
Most Simplest Implementation of Container _of macro is below , It reduces all complex checking of type and works
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))
ptr will give address of member and just subtract offset difference and you will
get start address.
Example usage
struct sample {
int mem1;
char mem2;
int mem3;
};
int main(void)
{
struct sample sample1;
printf("Address of Structure sample1 (Normal Method) = %p\n", &sample1);
printf("Address of Structure sample1 (container_of Method) = %p\n",
container_of(&sample1.mem3, struct sample, mem3));
return 0;
}
Related
I saw an interesting design for a doubly-linked-list inside the Pintos operating system and I don't quite understand how it was able to achieve this behavior. I wrote a small adaptation to demo what I'm referring to.
#include <stdio.h>
#include <stdint.h>
#include "list.h"
struct foo {
int x;
struct list_node node;
};
int main()
{
struct list list;
list_initialize(&list);
struct foo n1 = {1, NULL};
list_push_back(&list, &n1.node);
struct list_node *e = list_get_front(&list);
struct foo *ptr = list_entry(e, struct foo, node);
printf("%d", ptr->x);
return 0;
}
In essence, list.h implements two structures; namely, list and list_node. A list can be made for any arbitrary struct so long as the struct includes a list_node field. A reference to the structure can be returned by passing a pointer to it's list_node using the following macro defined in list.h.
#define list_entry(LIST_NODE, STRUCT, MEMBER) \
((STRUCT *) ((uint8_t *) &(LIST_NODE)->next \
- offsetof (STRUCT, MEMBER.next)))
The list_node struct declares a known field name, that is used to develop the result.
The key is found in the expression:
(uint8_t *)&(LIST_NODE)->next - offsetof (STRUCT, MEMBER.next)
offsetof() gives the offset in bytes of the specified field in the specified struct.
(uint8_t *)&(LIST_NODE)->next returns a byte pointer, that points to (the beginning of) the specified member of the specified node.
When you subtract the byte offset of the field from the pointer to the field, you get a byte pointer to (the beginning of) the struct.
The macro then casts this to a pointer to the struct.
I am reading Linux Device Drivers Development from John Madieu and one para says
The container_of macro won't work for char * or array members. It
means the first member of container_of must not be a pointer to
another pointer to char nor to array in the structure.
This is the definition of container_of :
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
So if I have
struct person {
int age;
int salary;
char *name;
} me;
and I have char ** my_name = &(me.name);, why can't I do the following :
struct person * me = container_of(my_name,struct person,name);
This is due to ISO C rules on pointer initialisations, which break the initialisation of __mptr for this case.
Here's a stripped-back example:
int main()
{
char ar[5] = {0};
const char (*ptr)[5] = &ar;
}
// warning: pointers to arrays with different qualifiers are incompatible in ISO C [-Wpedantic]
(live demo)
There is a discussion about this problem on a prior SO question. Note that C++ has no such limitation; the const may be added freely.
A kernel dev discussion suggested replacing __mptr with another way to perform the type check inside container_of, so you may find that this already no longer affects you.
Let's say we have a structure as follows (where T and U are any of the basic data types like int,long, char etc.)
struct S1 {
T t1;
U u1;
};
and another structure
struct S2 {
T t2;
U u2;
};
Now I allocate
struct S1* s1 = malloc(sizeof(*s1))
And withcontainer_of defined as
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) \
*__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
if I proceed to pass around T* x, the following could be done
struct S2* s2 = container_of(x, struct S2, t2)
//Here s2->u2 is the same value as that of s1->u1
Now my query is assuming that such operations occur oblivious to each other (in different libraries for eg.), this would lead to weird value modifications.
Context is:
I have my own code with S1, but when I pass t1 to another library code, that has another similar structure S2 and ends up modifying the value of u1 too. Is there any way to guard against such inadvertent use cases ? Also, let's say at each end of an interface, we have a T* x pointer, but both the interface implementer and the interface client for their usage purpose are storing it as part of structures S1 and S2. In that case too, the same situation may arise where mostly the server code would be unchangeable. How do we address this issue in those cases ?
A real example from the Kernel V4L2 framework here
static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
{
struct v4l2_buffer *b = pb;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
:
:
b->flags = vbuf->flags;
Now I had allocated a structure as follows:
my_v4l2_driver_video_buf{
struct vb2_buffer vb;
dma_addr_t addr;
}
and here's the definition of vb2_v4l2_buffer
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Note: dma_addr_t was 32bit too
And then I had passed pointer to vb to v4l2 framework. It modified the flags in the function __fill_v4l2_buffer and I ended up getting the v4l2_buffer* b 's flags set to the same dma_addr_t addr of my structure
I want to implement container_of macro/function from scratch like that is available in linux kernel to get the address of parent structure from the member of the parent structure.
e.g. if the parent structure is
struct parent{
int id;
struct list_head list; };
and i have the address of the list_head element inside the structure.
So i want to get the address of struct parent so that i can access id of the parent.
I have only three known information
1. Type of parent structure
2. Type of struct list_head
3. identifire/name of the list_head variable.
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
Thaks i any body can explain.
Firstly your question is not appropriate. From my understanding you want to understand the working of the macro, not implement it.
Moving on,
Linked lists used in the linux kernel are nicely explained in Linux Kernel Linked List Explained
In the linux kernel the list is contained in the list node.
Example:
struct list_head { /* Kernel list structure */
struct list_head *next, *prev;
}
struct my_list {
int to;
struct list_head list; /* list is contained in the node */
int from;
}
So we iterate the linked list using the list_head variable. The tricky part is that we use the list variable to get the node structure ( in which it is contained )
See Q. 2.14 and 2.15 in MIT FAQ. The question explains how we can retrieve pointer to the CONTAINING structure if we have the offset of a variable in the struct.
So in layman terms, we could say,
struct s address = <address of struct variable> - <offset of that variable in the struct>
Coming to the macro, consider this definition of the macro. (simplistic implementation, i found in drivers/gpu/drm/nouveau/include/nvif/list.h )
#define container_of(ptr, type, member) \
(type *)((char *)(ptr) - (char *) &((type *)0)->member)
So think of the left operand as the structure VARIABLE ( this is the list_head variable usually). Now coming to the right operator. To get the OFFSET of that variable ( say list_head variable ) in the containing strict ( say struct my_list ), we create a zeroed struct ( i.e., a temp struct with the address 0x0 ) so the addresses of any variables in the struct corresponds to the offset of that variable.
Now the last part to understand is why cast to char *. Well this basic pointer arithmetic. char * addtion would increment the values by 1 at a time ( char* points to a char of 1 byte ).
((char*)0) + 1 -> 0x1
Had it been int * addition of 1 to the pointer would increment the offset by 4 , as int * points to a int of size 4( on my computer).
((int*)0) + 1 -> 0x4
Hope that helped .. :)
This is an interview question. I have no idea how to solve it.
could anybody help me:?
Given a pointer to member a within a
structure, write a routine that
returns a pointer to the structure.
Thank you!
Firstly, in order to pull that off you need to know the type of the enclosing struct StructType and the name of the member member. That must be a given. Without it, the problem has no solution.
Secondly, I don't know why other answers insist on reinventing the wheel (and engage into undefined and non-portable hacks on top of that) instead of using the standard offsetof macro. With offsetof the answer is
StructType *pstruct =
(StructType *) ((char *) pmember - offsetof(StructType, member));
The Linux kernel code (GPLv2 licensed) includes a convenient container_of() macro:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
It is used like this:
static inline struct ext3_inode_info *EXT3_I(struct inode *inode)
{
return container_of(inode, struct ext3_inode_info, vfs_inode);
}
#Richard's answer is excellent; the main difference is this code is parameterized to accept any struct and any member, and as a result is correspondingly more complicated.
Given a structure named s and a member named m
struct s * BaseS(byte *p)
{
return (struct s *) (p - ((byte*) &(((struct s *)0)->m)));
}
The idea is to get the offset of the member and subtract that from the pointer.