【Linux 内核】container_of宏浅析

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执行结果:

猜你喜欢

转载自blog.csdn.net/zztingfeng/article/details/92372007