浅谈container_of

在Linux 内核中,container_of 函数使用非常广,例如 Linux内核链表 list_head、工作队列work_struct中,它的作用就是通过结构体内成员的地址来找到这个结构体的地址,现在我们就来看看它到底是个什么鬼东西

首先看看内核中它是如何定义的
在这里插入图片描述
原来是个宏,然后看下这个宏里边又包含了几处不太清楚的地方,我们来一一探究

1、typeof

typeof是GNU C对标准C的扩展,它的作用是根据变量获取变量的类型。
例如
在这里插入图片描述
它的输出结果就是
size a=4 size b=4 size c=8, size d=8

2、((type *)0)->member

大眼一看,这是个什么鬼东西,把0地址强转成一个结构体指针,然后访问其成员? 这有什么用呢? 说这么多还不如写个代码自己试试,直接上图了
在这里插入图片描述它的输出结果就是
((struct test_s *)0)->a=0 ->b=4 ->c=8

这好像就是各个变量相对于结构体本身的偏低地址,对了。就是这个作用,把0地址强转成结构体类型后,它的成员变量的相对地址就恰好等于其在结构体内的便宜地址。

3、offsetof

先来看看它在内核里的定义
在这里插入图片描述
发现是不是很熟悉,就跟我们前边的实验一模一样 有没有豁然开朗的感觉
到这里,这个container_of似乎不再这么神秘,大家应该能比较容易想到它是怎么实现的了。

比如:

struct test_s{
	char a;
	int b;
	float c;
	short d;
}test;

如果我们要通过c的地址来找到这个test的地址,那我们只需要找到c成员相对于test的偏移地址即可。
即&test = &(test.c) - offset;
是不是觉得so easy?

好了,主要的部分就已经讲完了,有没有人好奇const typeof( ((type *)0)->member ) *__mptr = (ptr) 这个放在这到底有什么意义,这个展开后其实就是 int *mptr = ptr;
好像跟我们的主体没什么关系,去掉也可以对不对。然而这才是内核严谨的地方,这个地方唯一的作用是验证参数的类型匹不匹配,如果传入的参数不匹配,编译后会有警告信息,帮助程序员更好的定位问题点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值