Chinaunix首页 | 论坛 | 博客
  • 博客访问: 316571
  • 博文数量: 63
  • 博客积分: 2018
  • 博客等级: 大尉
  • 技术积分: 694
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-23 16:34
文章存档

2010年(63)

我的朋友

分类: LINUX

2010-11-04 18:26:24

在学习Linux驱动的过程中,遇到一个宏叫做container_of。
该宏定义在include/linux/kernel.h中,首先来贴出它的代码:
1.       439/** 
2.       440 * container_of - cast a member of a structure out to the containing structure 
3.       441 * @ptr:        the pointer to the member. 
4.       442 * @type:       the type of the container struct this is embedded in. 
5.       443 * @member:     the name of the member within the struct. 
6.       444 * 
7.       445 */ 
8.       446 #define container_of(ptr, type, member) ({                      \ 
9.       447        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \ 
10.      448      (type *)( (char *)__mptr - offsetof(type,member) );})
 
它的作用显而易见,那就是根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针。比如,有一个结构体变量,其定义如下:
1.       struct demo_struct { 
2.           type1 member1; 
3.           type2 member2; 
4.           type3 member3; 
5.           type4 member4; 
6.       }; 
7.        
8.       struct demo_struct demo;
同时,在另一个地方,获得了变量demo中的某一个域成员变量的指针,比如:
1.       type3  *memp = get_member_pointer_from_somewhere();
此时,如果需要获取指向整个结构体变量的指针,而不仅仅只是其某一个域成员变量的指针,我们就可以这么做:
1.       struct demo_struct *demop = container_of(memp, struct demo_struct, member3);
这样,我们就通过一个结构体变量的一个域成员变量的指针获得了整个结构体变量的指针。

下面说一说我对于这个container_of的实现的理解:
首先,我们将container_of(memp, struct demo_struct, type3)根据宏的定义进行展开如下:
1.       struct demo_struct *demop = ({                      \ 
2.           const typeof( ((struct demo_struct *)0)->member3 ) *__mptr = (memp);    \ 
3.           (struct demo_struct *)( (char *)__mptr - offsetof(struct demo_struct, member3) );})
其中,typeof是GNU C对标准C的扩展,它的作用是根据变量获取变量的类型。因此,上述代码中的第2行的作用是首先使用typeof获取结构体域变量member3的类型为 type3,然后定义了一个type3指针类型的临时变量__mptr,并将实际结构体变量中的域变量的指针memp的值赋给临时变量__mptr。
 
(char *)__mptr转换为字节型指针。(char *)__mptr - offsetof(type,member) )用来求出结构体起始地址(为char *型指针),然后(type *)( (char *)__mptr - offsetof(type,member) )在(type *)作用下进行将字节型的结构体起始指针转换为type *型的结构体起始指针。


假设结构体变量demo在实际内存中的位置如下图所示:
     demo
 +-------------+ 0xA000
 |   member1   |
 +-------------+ 0xA004
 |   member2   |
 +-------------+ 0xA010
 |   member3   |
 +-------------+ 0xA018
 |   member4   |
 +-------------+

则,在执行了上述代码的第2行之后__mptr的值即为0xA010。

再看上述代码的第3行,其中需要说明的是offsetof,它定义在include/linux/stddef.h中,其?
阅读(2129) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-11-05 14:46:28

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com