Hi,欢迎来到嵌入式培训高端品牌 - 华清远见教育科技集团<北京总部官网>,专注嵌入式工程师培养15年!
当前位置: > 华清远见教育科技集团 > 嵌入式学习 > 讲师博文 > 揭开linux内核中container_of的神秘面纱
揭开linux内核中container_of的神秘面纱
时间:2016-12-22作者:华清远见

在linux 内核中有一个大名鼎鼎的宏container_of(),这个宏是用来干嘛的呢?我们先来看看它在内核中是怎样定义的。

呵呵,乍一看不知道是什么东东。

我们先来分析一下container_of(ptr,type,member),这里面有ptr,type,member分别代表指针、类型、成员。看一个例子:

Struct test
        {
                int i;
                int j;
                char k;
        };
        Struct test temp;

现在呢如果我想通过temp.j的地址找到temp的首地址就可以使用container_of(&temp.j,struct test,j);

现在我们知道container_of()的作用就是通过一个结构变量中一个成员的地址找到这个结构体变量的首地址。

下面来看看比较复杂的内容:

我们用上面的struct test张展一下

Const typeof(((struct test *)0)->j) * __mptr = (&temp.j);

其中,typeof是GNU C对标准C的扩展,它的作用是根据变量获取变量的类型。因此,上述代码的作用是首先使用typeof获取结构体成员j的类型为int,然后顶一个int指针类型的临时变量__mptr,并将结构体变量中的成员的地址赋给临时变量__mptr。

(struct test *)((char *)__mptr - offsetof(struct test,j));

接着我们来看一下offsetof(struct test,j),他在内核中如下定义

展开(size_t)&((struct test *)0)->j,这是什么东东?

一开始也不明白,这里要感谢曹老师老师的热心帮助,一语惊醒梦中人,呵呵,可以是这样理解。

其中size_t是整型,那么我们可以知道终的结果是一个整形值,也就是j相对于0地址的偏移量。也许现在你会问,整出这么个玩意干嘛,下面看个列子:

程序运行结果:

发现没有如果把第二个值 减去后一个值,就能得到第一个值。

在回首一下它:

(struct test *)((char *)__mptr - offsetof(struct test,j));

是不是可以获得结构体变量temp的首地址呀,是不是太精妙了呀,linux内核中随随便便一个宏就有如此精妙,呵呵,想想对linux了解非常多的牛人,还有很长一段路。

发表评论
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)