众所周知,Container_of是Linux内核中常用的宏,用来从一个结构中包含的指针中获取一个结构本身的指针。通俗地说,就是通过结构变量中某个成员的首地址来获取整个结构变量的首地址。本文详细介绍了Container_of。如果有需要,可以参考一下。
前言
在linux内核中,函数的container_of应用非常广泛,比如linux内核链表_head和工作队列work_struct。
linux内核中众所周知的宏container_of(),其实它的语法很简单,只是一些指针的灵活应用。它分为两个步骤:
第一步,先定义一个与ptr数据类型相同的临时指针变量__mptr(由typeof ((type *) 0)-member获得),然后用它保存ptr的值。
第二步:用(char *)__mptr减去结构中成员的偏移量,得到整个结构变量的第一个地址(整个宏的返回值就是这个第一个地址)。
那么这个宏到底是用来做什么的呢?我们先来看看它是如何在内核中定义的。
呵呵,一看就不知道是什么。
我们先分析一下container_of(ptr,type,member),其中ptr,type,member分别代表指针,类型,成员。
看一个例子:
结构测试
{
int I;
int j;
char k;
};
结构测试温度;
现在如果我想通过temp.j的地址找到temp的第一个地址,可以用container _ of (temp.j,struct test,j);
现在我们知道container_of()的作用是通过结构变量中某个成员的地址找到结构变量的第一个地址。
让我们来看看更复杂的内容:
让我们使用上面的结构测试来张展它。
const type of((struct test *)0)-j)* _ _ mptr=(temp . j);//(sturct test *)0表示数据段的基址。
其中,typeof是GNU C对标准C的扩展,其作用是根据它们获取变量的类型。所以上面这段代码的作用就是先通过使用typeof获取结构成员J的类型为int的临时变量__mptr,然后将结构变量中成员的地址赋给临时变量__mptr。
(struct test *)((char *)_ _ mptr-offset of(struct test,j));
让我们来看看offsetof(struct test,j),它在内核中的定义如下
expand(size _ t)((struct test *)0)-j,这是什么?
一开始,我也不理解。我要感谢曹中铭的热情帮助,唤醒了梦想者。呵呵,可以这么理解。
其中size_t是一个整数,那么我们就可以知道最后的结果是一个整数值,也就是J距离0地址的偏移量。现在你可能会问,为什么要做出这样的事情?这里有一个列表:
程序运行结果:
发现如果从最后一个值中减去第二个值,就可以得到第一个值。
回过头来看:
(struct test *)((char *)_ _ mptr-offset of(struct test,j));
你能得到结构变量temp的第一个地址吗?是不是太含蓄了?
总结
仅仅是linux内核中的一个宏就如此微妙。想不到对linux很了解的牛逼的人,还有很长的路要走。好了,这就是本文的全部内容。希望本文内容对大家的工作学习有所帮助。有问题可以留言交流。谢谢你的支持。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。