Linux内核中关于宏container_of的使用

在Linux内核代码中多处使用了宏container_of,关于container_of 的宏的定义在include/linux/kernel.h

/**
 * 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) );})

container_of宏中的参数ptr代表指针、type代表类型、member代表成员
简单的来说:container_of宏的作用是通过结构体中一个成员的地址找到这个结构体

struct test{
	 char data;
	 struct test * next;
	 int num;
};
struct test temp;

假如此时我们只有temp.num的地址,如何找到temp的首地址去访问它的其它成员呢?
使用宏container_of:container_of(&temp.num, struct test, num)
container_of宏展开:
第一行:
const typeof( ((type *)0)->num) *__mptr = (&temp.num)
typeof是GNU C对标准C的扩展,它的作用是根据变量获取变量的类型,这里是获取结构体中num的类型,所以这一行代码其实就是定义了__mptr是一个指向num类型变量的指针,并将temp.num的地址赋给它。
第二行:
(type *)( (char *)__mptr - offsetof(struct test,num) )
offsetof宏的定义在 include/linux/stddef.h #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE )0)->MEMBER)
把offsetof宏展开(size_t) &((type
)0)->num,定义了0地址并强制转换成指向type类型的指针,在取出其中成员num的地址,这一步其实就能计算出num成员基于结构体首地址的偏移值。

总结:
(type *)( (char *)__mptr - offsetof(struct test,num) ) 就是成员num的地址 - num成员基于struct test首地址的偏移值,最终得到struct test的首地址。

代码demo:

struct test{
	 char data;
	 struct test *next;
	 int num;
};
struct test temp;
printf("结构体temp的首地址:%p \n",&temp);
printf("成员num地址:%p \n",&temp.num);
printf("-------------------------------\n");
printf("调用container_of(&temp.num,struct test,num):%p \n",
  container_of(&temp.num, struct test, num));
printf("-------------------------------\n");  
printf("num基于test基地址的偏移(size_t) &((struct test *)0->num: %ld \n)",(size_t)&((struct test *)0)->num);

运行后结果:
在这里插入图片描述
看运行结果验证container_of运行后的作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值