从基本理解到深入探究 Linux kernel container_of 宏

基本理解container_of 宏

container_of,顾名思义就是某某某的容器,也就是说某某某成员变量所在的结构体是谁。

struct cntner {
   
   
	int i;	char c;	float f;
};
struct cntner init_struct ={
   
   .i=2019,'a',0.0120};
char *pc = &init_struct.c;
// 参数1:指向该结构体成员变量的指针;参数2:该结构体变量类型;参数3:该结构体成员变量名
struct cntner *pcntner = container_of(pc, struct cntner, c);
// 然后就可以使用pcntner结构体指针寻找其他成员的值了
printf("init_struct.i = %d\n", pcntner->i); 
printf("init_struct.c = %c\n", pcntner->c); 
printf("init_struct.f = %f\n", pcntner->f);

有人会问为什么不用init_struct 访问成员变量呢?如果你看了相关系统源码你就知道,很多时候我们访问不了这个结构体变量,只知道其成员,所以用了此招 container_of。

static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
{
   
   
    struct fb_event *evdata = data;
    int *blank;
    struct xxx_ts_data *xxx_data = container_of(self, struct xxx_ts_data, fb_notif);
    ...
}

一般会使用这个宏接口就行了,若不想放弃请看下面深入探究container_of 宏。

深入探究container_of 宏

计算出结构体cntner 的地址其实就是通过变量的地址减去自己的偏移量,就这么简单。

cntner_addr = addr_c - offsetof_c

其中变量c的偏移量offsetof_c = &((struct cntner *)0)->c0被强制转化为结构体是不是很高级,其实就是起始地址为0的结构体,然后指向变量c取地址就是c的偏移量。
 container_of
注:本文代码测试在64位的ubuntu系统中,关于上面字节对齐疑问请参见:https://blog.csdn.net/u014134180/article/details/78335328#6_488

我们看看下面几个container_of 宏的实现:

container_of 宏 版本一

这个宏定义出自 msm-4.9\drivers\gpu\drm\nouveau\include\nvif\list.h

/**
 * Returns a pointer to the container of this list element.
 *
 * Example:
 * struct foo* f;
 * f = container_of(&foo->entry, struct foo, entry);
 * assert(f == foo);
 *
 * @param ptr Pointer to the struct list_head.
 * @param type Data type of the list element.
 * @param member Member name of the struct list_head field in the list element.
 * @return A pointer to the data struct containing the list head.
 */
#ifndef container_of
#define container_of(ptr, type, member) 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值