How to Use container_of in Linux Kernel Development

In this post, I will explain the usage of linux's container_of macro with a sample code.

If you know address of a data structure's field, you can get the address of the instance of that data structure by using the container_of macro. This is the simplest explanation of this macro.

Let's say you have a function called with a pointer parameter and you know that the pointer is pointing an address of a data structure field.

struct my_object {
        int a;
        int b;
} obj;

function(&obj->b);

If you want to access the other field "a" in the function, you need to use container_of macro.

Let's see the below sample code and it's output to understand it easily.

/*
 * my_object structure.
 */
struct my_object {
        int a;
        int b;
        int c;
};

/*
 * container_test()
 *      Test function for usage of container_of macro.
 *
 * This function is passed a pointer which points a field of
 * an allocated my_object instance and prints the address of the
 * object and its other fields.
 */
static void container_test(int *val)
{       
        struct my_object *obj;
        
        obj = container_of(val, struct my_object, b);
        
        printk(KERN_INFO "obj obtained by container_of macro using &obj->b\n");
        printk(KERN_INFO "obj: %p obj->a: %d obj->b: %d obj->c: %d\n",
                obj, obj->a, obj->b, obj->c);
}

/*
 * container_init()
 */
static int container_init(void)
{
        struct my_object *obj;

        printk(KERN_INFO "container init\n");

        /*
         * Allocate an instance of my_object.
         */
        obj = kmalloc(sizeof(struct my_object), GFP_KERNEL);
        if (!obj) {
                printk(KERN_WARNING "unable to allocate memory\n");
                return -1;
        }

        /*
         * Initialize the fields of the object.
         */
        obj->a = 5;
        obj->b = 15;
        obj->c = 25;

        printk(KERN_INFO "Allocated and initialized object\n");
        printk(KERN_INFO "obj: %p obj->a: %d obj->b: %d obj->c: %d\n",
                obj, obj->a, obj->b, obj->c);

        /*
         * Call the test function with the address of the field b.
         */
        container_test(&obj->b);

        kfree(obj);

        return 0;
}


OUTPUT:

Allocated and initialized object
obj: b5a07100 obj->a: 5 obj->b: 15 obj->c: 25

obj obtained by container_of macro using &obj->b
obj: b5a07100 obj->a: 5 obj->b: 15 obj->c: 25


Source Code Download:




Comments

Popular posts from this blog

Notification Chains in Linux Kernel

Linux Dynamic Debugging