Linux教程

Linux内核——container_of

本文主要是介绍Linux内核——container_of,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在驱动过程中,一直有一个做法,就是通过,我知道的一个结构体的一个成员,那么我就可以拿到整个结构体的数据
我们也称为以小博大。
就比如字符设备驱动过程中的input_dev input_handler 和evdev_handl 这三个结构体就天天在那博来博去的。
乍一想:就是通过,我知道的一个结构体的一个成员,那么我就可以拿到整个结构体的数据。
这肯定没问题啊,我都知道一个成员了,那拿到整个结构体的数据这不是易如反掌吗?

但是真的让你去操作你会怎么操作



内核是定义一个宏去完成以小博大

container_of:
#define container_of(ptr, type, member) ({          
        const typeof( ((type *)0)->member ) *__mptr = (ptr); 
        (type *)( (char *)__mptr - offsetof(type,member) );
        })  

它这里面还定义了俩个宏支持这个宏

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)  
还有一个typeof的宏

typeof:这个宏就是可以获取到一个变量的类型,如我们可以这样写代码:{int a; typeof(a) b;}这段代码等价于:{int a; int b;}

接下来看一个很有意识的宏
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
首先定义了一个宏叫 offsetof
它可以传递参数(TYPE, MEMBER) 一个是结构体类型 一个是已经知道的成员
它用来替换掉了:
((size_t) &((TYPE *)0)->MEMBER)
慢慢分析
(TYPE *)0 :这个的意识就是 我把0强制转化成type的地址 那么这个就是一个type的0地址。
((TYPE *)0)->MEMBER) :这个就是我在0地址创建了一个type类型的结构体 ,我们还知道它有一个成员MEMBER;
&((TYPE *)0)->MEMBER) :这样我就拿到了以0为起始地址的type类型的结构体,的已知成员的的地址。
((size_t) &((TYPE *)0)->MEMBER) :把它强转成((size_t)型,就是偏移量了。
在这里插入图片描述
所以说,这个宏求出了这个成员在结构体中的偏移量,
那 我成员地址有了,偏移量有了,不就可以找到结构体首地址了吗?

这篇关于Linux内核——container_of的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!