linux中container_of详解

作用

根据一个结构体变量中的一个成员变量的指针来获取指向整个结构体变量的指针

详解

container_of出现在linux/kernel.h中,定义如下:

/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:	the pointer to the member.
 * @type:	the type of the container struct this is embedded in.
 * @member:	the name of the member within the struct.
 *
 */
#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)

ptr是成员变量的指针, type是指结构体的类型, member是成员变量的名字。

typeof

首先看下typeof,是用于返回一个变量的类型,这是GCC编译器的一个扩展功能,也就是说typeof是编译器相关的。既不是C语言规范的所要求,也不是某个标准的一部分。

(((type *)0)->member)

((TYPE *)0)将0转换为type类型的结构体指针,换句话说就是让编译器认为这个结构体是开始于程序段起始位置0,开始于0地址的话,我们得到的成员变量的地址就直接等于成员变量的偏移地址了。 (((type *)0)->member) 引用结构体中MEMBER成员。

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

这句代码意思是用typeof()获取结构体里member成员属性的类型,然后定义一个该类型的临时指针变量__mptr,并将ptr所指向的member的地址赋给__mptr; 为什么不直接使用 ptr 而要多此一举呢? 我想可能是为了避免对 ptr 及prt 指向的内容造成破坏。

offsetof(type, member))

((size_t) &((TYPE*)0)->MEMBER)

size_t定义和架构有关
在这里插入图片描述

size_t是一个非负数,所以size_t通常用来计数(因为计数不需要负数区)
为了使程序有很好的移植性,因此内核使用size_t和,而不是int,unsigned。 ((size_t) &((TYPE*)0)->MEMBER) 结合之前的解释,我们可以知道这句话的意思就是求出MEMBER相对于0地址的一个偏移值。

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

这句话的意思就是,把 __mptr 转换成 char * 类型, 因为 offsetof 得到的偏移量是以字节为单位。 两者相减得到结构体的起始位置, 再强制转换成 type 类型。

举例

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

typedef struct student
{
    int id;
    char name[30];
    int math;
}Student;

int main()
{
          Student stu;
        Student *sptr = NULL;
        stu.id = 123456;
        strcpy(stu.name,"feizhufeifei");
        stu.math = 90;
        sptr = container_of(&stu.id,Student,id);
        printf("sptr=%p\n",sptr);
        sptr = container_of(&stu.name,Student,name);
        printf("sptr=%p\n",sptr);
        sptr = container_of(&stu.math,Student,id);
        printf("sptr=%p\n",sptr);
        return 0;    
}

结果:

sptr=0xffffcb90
sptr=0xffffcb94
sptr=0xffffcbb4
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Linux内核container_of是一个宏定义,用于获取包含某个成员的结构体变量的地址。它的定义可以在include/linux/kernel.h找到。该宏的作用是通过给定的成员指针,返回包含该成员的结构体变量的地址。具体的定义如下: ```c #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) ``` 这个宏的使用非常方便,可以通过成员指针来获取整个结构体变量的地址。在进行内核驱动开发时,经常会用到这个宏来获取结构体变量的地址,以便进行相关操作。 #### 引用[.reference_title] - *1* [Linux内核:理解container_of宏](https://blog.csdn.net/qq_28877125/article/details/124209504)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Linux内核container_of的原理及其使用详解](https://blog.csdn.net/u010632165/article/details/107523477)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值