现在的位置: 首页 > 综合 > 正文

神奇的container_of

2013年09月03日 ⁄ 综合 ⁄ 共 1281字 ⁄ 字号 评论关闭

container_of是linux内核中常用的一个宏,这个宏的功能是,根据某个结构体字段的指针,找到对应的结构体指针。

话不多说,先上源码:

/**
* container_of - cast a member of a structure out to the containing structure
* @ptr:        the pointer to the member.
* @type:       the type of the container struct this is embedded in.
* @member:     the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

第一个参数为指向结构体中的成员的指针,第二个参数为结构体类型,第三个参数为结构体成员的名字。

 
如图,一个结构体struct a中包含三个成员b,c,d,一个指向成员c的指针p_c,通过container_of(p_c, struct a, c)就可以计算出指向c所在的结构体的指针p_a


原理说明:
这个宏的原理是结构体成员指针ptr,减去结构体成员与此结构体首地址的偏移量(这个偏移量由offsetof宏获得),就得出了结构体首地址。这个功能是由宏声明的第三行实现的。
那么宏声明的那二行是干什么用的呢?它仅仅是把ptr重新赋值给了__mptr,看似没用。实际上这里起到了给开发者提醒的功能。如果开发者传入的ptr指针指向的类型,与结构体中成员的类型不符,编译器在这里会打印一条warning,提示开发者可能存在的错误。

测试代码:
#include <stdio.h>
#include <linux/kernel.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 a {
                 int b ;
                 int c ;
                 int d ;
};

int main( int argc, char *argv[])
{
                 struct a a_obj, *p_a;
                 int *p_c;

                p_c = &a_obj. c ;
                p_a = container_of(p_c, struct a, c);

                 printf ("a_obj addr:%x\na_obj addr obtained by container_of: %x\n", ( unsigned int )&a_obj, ( unsigned int )p_a);

                 return 0;
}
打印结果:
a_obj addr:bfffed98
a_obj addr obtained by container_of: bfffed98

抱歉!评论已关闭.