内核工作函数container_of的使用和原理分析

在编写驱动程序时通常自定义一个数据结构来存储全局变量。当涉及到工作队列work_struct时,可以把work_struct嵌入到上述说的自定义数据结构中,利用container_of传递特征,即可实现不使用全局变量而可以访问全局变量的效果。

//定义一个含有work_struct工作队列结构体的结构体

struct mydata{

   int x;

   int y;

   struct work_struct work;

   int z;

};

//定义一个结构体drvdata

static struct mydata drvdata;

在模块加载初始化函数中调度工作队列。

static int __init xxx_init(void)

{

   ………

   schedule_work();

………

}

此时重点关注到调用的工作函数中。我们需要通过传进的work_struct来定位到全局变量结构struct mydata drvdata的首地址。

static void mywork_func(struct work_struct *pwork)

{

   struct mydata *pdata;

   ……

   pdata = (struct mydata *)container_of(pwork,struct pdata,work);

   ……

}

来看container_of的函数原型:container_of(ptr, type, member)。

第一个参数是已知的成员变量内存地址,第二个参数传入已知成员所在结构体的变量类型,第三个参数传入已知成员所在的结构体变量类型中的成员名。可以根据已知成员的内存地址,求出含有其的所在结构体变量内存首地址。

原理分析:

结构体变量首地址 = (char *)ptr – ptr在结构中的偏移。假设偏移的地址大小是offset,关键就是求出offset的值。

所以假设结构体变量drvdata在0地址,因此offset就是ptr的所在地址。则p = ((struct mydata*)0),(u32)(&p->work)就是offset的大小

1、(type *)0,把0地址强制转换为type类型变量,用一个指针指向它。

2、((type *)0->member)通过上一步转换得到的指针访问type类型中的member

3、typeof((type *)0->member),typeof是c语言32个关键字之一,作用是根据变量名求出变量类型。

4、const typeof((type *)0->member) *mptr,定义一个已知成员类型的临时指针变量,保存已知成员的地址。

5、(char *)_mptr把已知成员地址转换为char *类型的指针,方便计算出偏移的大小

6、offsetof(type,member)。Offsetof是一个宏定义作用是求出type类型中已知成员member在type结构中偏移的字节。

7、(char *)__mptr – offsetof(type,member),使用已知成员的真实地址减去成员所在结构的实际偏移量,得到结构体变量首地址。

8、((type *)(char *)__mptr – offsetof(type,member))最后把已求出的(char *)地址转换为type*地址。

内核的函数只要知道其如何使用即可,无需太过于深入了解。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

D584640810

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值