Monday, February 21, 2011

How "container_of" macro works, & an Example

Here iam giving a small code snippet that gives and idea about working of "container_of", this posed me little difficulty in understanding, after google-ing i got some examples and after working on that i wrote a simple C application that depicts its working. here i have defined two macros "offsetof" and "container_of" which i have extracted from "kernel.h" header. 
       Please interpret this code and try some trick to understand "container_of".

container_of macro is defined in linux/kernel.h

syntax: container_of( pointer, container_type, container_field );

This macro takes a pointer to a filed name container_field, within a structure of type container_type, and returns a pointer to the containing structure .

simply this is a convenience macro that may be used to obtain a pointer to a structure from a pointer to some other structure contained with in it.


Code :

#include <stdio.h>
#include <stdlib.h>

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({            \
 const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
 (type *)( (char *)__mptr - offsetof(type,member) );})

struct test1 {
 int a;
};

struct test2 {
 int b;
 struct test1 z;
 int c;
};

int main()
{
 /* existing structure */
 struct test2 *obj;
 obj = malloc(sizeof(struct test2));
 if(obj == NULL){
       printf("Error: Memory not allocated...!\n");
 }
 obj->z.a = 51;
 obj->b = 43;
 obj->c = 53;
 
 /* pointer to existing entry */    
 struct test1 *obj1 = &obj->z;

 struct test2 *obj2 = container_of(obj1, struct test2, z);

 printf("obj2->b = %d\n", obj2->b);

 return EXIT_SUCCESS;
}

Note: Copying the code directly into your source.c file will also copies the invisible characters and finally you will left out with stray errors, i recommend you to type the code and that even becomes a practice.

for more information check out this : http://www.kroah.com/log/linux/container_of.html

7 comments: