Linux内核:container_of宏分析

我们在编写驱动程序的时候,会经常在open函数中用到container_of宏,那么这个在linux内核中这个宏的主要作用是什么呢?
所在linux目录
tool\perf\util\include\linux\Kernel.h

主要功能
首先简述一下container_of的主要功能:对于给定结构体成员的地址,从而找到该结构体的首地址。换句话说就是,如果已经知道了一个结构体成员的地址,那么通过container_of函数就可以知道该结构体的入口地址,也就是首地址啦。

参数分析
首先看一下container_of的表达式:container_of(ptr,type,member),从表达式可以看出container_of宏一共需要三个参数,下面分别介绍:

ptr: 结构体成员的地址或者指针
type: 结构体类型
member: 成员名称

通过这三个参数,就可以返回该结构体的首地址了。

例子分析
结构体

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

现在呢,如果我想通过temp.j的地址找到结构体temp的首地址,就可以使用我们的container_of宏。

container_of(&temp.j, struct test, j);

源代码分析
首先来看一下我们的源代码:

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

第一段代码是:

const typeof(((type *)0)->member) * __mptr = (ptr);

这里linux内核使用了一个typeof函数,typeof是GNU对标准C的扩展,它的作用是根据变量获取变量类型,而(type )0则表示type结构体指针0的成员变量member,因此typeof(((type )0)->member)则表示member的变量类型,从而_mptr就表示为member类型的指针变量,同时指向ptr指针,也就是说将ptr指向的地址赋给了_member指针变量。

我们再来看第二句代码:

(type *)((char *)__mptr - offsetof(type, member));

这句代码相对比较复杂,我们详细分析下,首先由左边的( type * ),我们知道这条代码的返回值类型为type指针类型。而对于((char *)__mptr - offsetof(type, member)),我们要了解offsetof的作用。
offsetof的表达式为offsetof(TYPE, MEMBER),表示为type与member的相对地址差。因此我们便知道了((char *)__mptr - offsetof(type, member))表示_mptr地址减去type与member的相对地址差,从而得到结构体type的首地址。

你可能感兴趣的:(linux驱动,linux内核)