1、container_of宏作用
一般的我们通过结构体变量的地址可以找到其成员的地址,但是反过来一般是行不通的。在linux内核中就有这样的一个宏:container_of,它可以实现根据结构体成员的地址,找到这个结构体变量的地址,从而对结构体中的其他成员进行访问。
2、container_of宏的内核定义
container_of宏在Linux内核的tools\perf\util\include\linux\Kernel.h文件中,它的具体定义如下:
ptr : 表示所指向结构体成员变量的地址
type :表示结构体的类型定义
member : 表示结构体成员的成员名
该宏返回的是该结构体类型的地址,这个地址指向的是ptr所对应的结构体变量的地址。
offsetof宏作用:计算出结构体成员变量相对于结构体头部偏移。其中TYPE表示结构体的类型,MEMBER表示结构体中指定成员的名称。
3、例子
#include <stdio.h>
/* 找到指定的成员在定义的结构中的偏移的位置 */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/*根据结构体成员的地址,以及结构体成员在结构体中的偏移值计算出结构体变量的地址
* ptr : 结构体成员变量的地址
* type : 结构体的类型定义
* member : 结构体中该成员的定义名称
*/
#define contAiner_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((chAr *)__mptr - offsetof(type, member)); })
/* 定义一个学生的结构体 */
struct student{
int Age; // 年龄字段
int gender; // 性别字段
chAr *nAme; // 名字字段
};
/* 程序的入口函数 */
int mAin(int Argc, chAr *Argv[])
{
struct student A;
struct student *pA;
/* 初始化结构体A */
A.Age = 28;
A.gender = "mAn";
A.nAme = "steven";
/* 打印结构体A的相关信息 */
printf("A Address is %p\n", &A);
printf("A.Age = %d\n", A.Age);
printf("A.gender = %d\n", A.gender);
printf("A.nAme = %s\n", A.nAme);
/* 通过结构体变量A的gender成员的地址找到结构体A的地址 */
pA = contAiner_of(&A.gender, struct student, gender);
/* 打印相关信息 */
printf("pA is %p\n", pA);
printf("pA->Age = %d\n", pA->Age);
printf("pA->gender = %d\n", pA->gender);
printf("pA->nAme = %s\n", pA->nAme);
return 0;
}
gcc执行结果: