Linux常用宏contianer_of()

Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。

Container_of的定义如下: 

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

它分两步:

    第一步,首先定义一个临时的数据类型(通过typeof( ((type *)0)->member )获得)与ptr相同的指针变量__mptr,然后用它来保存ptr的值。

    第二步,用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。

理解这个宏,首先需要知道:

1:每个结构体的访问,都被编译器转换成了对地址的访问,并且地址是随机的;

2:对于结构体成员的访问,都是通过结构体的随机首地址+成员的偏移来实现的;(编译期间已经静态的知道成员的大小,从而知道了相对偏移)

对了,

代码中可以写类似于int *ptr = 0x1234567;这样的语句代码,对ptr执行加、减,甚至强制类型转换都没有任何问题,但是如果你想访问ptr地址里的内容,可能会收到一个“Segmentation Fault”的错误提示,因为你访问了非法的内存地址。

回过去看contianer_of()这个宏,其中有个typeof方法,用于取变量的类型;这属于GCC编译器的特性,而非C语言的特性;

因此,意思是用typeof()获取结构体里member成员属性的类型,然后定义一个该类型的临时指针变量__mptr,并将ptr所指向的member的地址赋给__mptr;之后,__mptr减去它自身在结构体type里的偏移量就找到了结构体的入口地址,最后将该地址强转成目标

结构体的地址类型就OK了;

部分来源:https://blog.csdn.net/npy_lp/article/details/7010752

原文地址:https://www.cnblogs.com/rex-2018-cloud/p/10529457.html