Chinaunix首页 | 论坛 | 博客
  • 博客访问: 110297
  • 博文数量: 24
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 270
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-30 18:17
文章分类

全部博文(24)

文章存档

2010年(21)

2009年(3)

我的朋友

分类: LINUX

2009-12-01 14:48:00

linux内核中经常可以看到container_of的身影,也是linux引以为豪的地方之一了。《linux设备驱动开发详解》132页对container_of的作用作了说明——通过结构体成员的指针找到这个成员所在结构体的指针。但没有具体分析它是怎么实现的。

下面我们先看看这个宏的定义:

/**

 * 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) );})


参数ptr是结构体typ的成员member的指针,我们很多时候希望得到结构体type的起始地址,也就是type的指针。

 

假设这个type在内存中的存储模型如下:

            type
      |----------|
      |          |
      |          |
      |----------|

ptr->|   member --|
      |----------|
      |          |
      |          |
      |----------|


这里,我们拆开来就好理解了:

首先,(type *)0)是把0地址转化为TYPE结构的指针(这里把0换成其它值也是一样的);

((type *)0)->member   type结构体中的member成员;

typeof( ((type *)0)->member )  返回member的类型;

const typeof( ((type *)0)->member ) *__mptr = (ptr);  用上面这个类型定义一个指针__mptr,并把ptr赋值给它;

(char *)__mptr   __mptr转化成char型指针;

offsetof宏定义在[include/linux/stddef.h]中定义为:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
这里,说明一下这个宏,((size_t) &((TYPE *)0)->MEMBER)0地址转化为TYPE结构的指针,然后获取该结构中MEMBER成员的指针,并将其强制转换为size_t类型。于是,由于结构从0地址开始定义,因此,这样求出的MEMBER成员地址,实际上就是它在结构中的偏移量。这也显示出了C语言中指针的强大。因为,在某个体系结构下实现的libc,结构中各个成员的偏移总是可以预见的。

现在有了member成员在type结构体中的偏移量,又有了指向member的指针__mptr,自然就可以计算出type结构的起始地址了。
小小一个宏就包括了这么多精华,可见linux的博大。

------------------------------------------
本文乃原创!
转载请注明出处:http://sparklecliz.cublog.cn/
------------------------------------------
阅读(2294) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:Linux驱动之input子系统浅析

给主人留下些什么吧!~~