Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1170316
  • 博文数量: 173
  • 博客积分: 4048
  • 博客等级:
  • 技术积分: 2679
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-12 18:53
文章分类

全部博文(173)

文章存档

2018年(1)

2016年(1)

2013年(1)

2012年(118)

2011年(52)

分类: LINUX

2011-08-08 15:08:18

linux驱动中会用到linux/kernel.h中的container_of宏:
container_of(ptr, type, member)
ptr为type结构体类型中member成员的指针。结果返回包含ptr指针指向member成员的结构体。
例如在linux字符驱动中:
  1. struct scull_dev {
  2.      struct scull_qset *data;
  3.      int quantum;
  4.      int qset;
  5.      unsigned long size;
  6.      unsigned int access_key;
  7.      struct semaphore sem;
  8.      struct cdev cdev; //内嵌linux内核定义的cdev结构体
  9. };
已知一个cdev指针的话就可以这样获得对应的struct scull_dev结构。
  1. container_of(inode->i_cdev,struct scull_dev,cdev);
container_of宏的实现代码如下:
  1. #define container_of(ptr, type, member) ({ \
  2.   const typeof( ((type *)0)->member ) *__mptr = (ptr); \
  3.   (type *)( (char *)__mptr - offsetof(type,member) );})
首先定义一个__mptr指针赋值为ptr指针。
然后使__mptr指针回退member成员在type结构体中的偏移地址。其中使用offsetof宏如下:
  1. #define offsetof(s, m) (size_t)&(((s *)0)->m)
是的,代码非常简单。其思想是,假如结构体处于0地址,获取其成员的地址。这个地址就是成员相对于结构体初始地址的偏移量了。没错0地址是不能运行时访问 的,但这句代码只在编译期使用了0地址,因此是合法的。当然其实使用成员指针和结构体指针相减也可做到,但用这种方式可以减少一次运算,确保了这个宏可以 在编译期求出结果。可谓是精益求精。
阅读(1269) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~