Chinaunix首页 | 论坛 | 博客
  • 博客访问: 376871
  • 博文数量: 263
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1975
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-05 09:59
文章分类

全部博文(263)

文章存档

2015年(166)

2014年(97)

分类: LINUX

2014-09-20 15:20:09

在linux下很多地方使用了list_entry(链表结构实现), rb_entry(红黑树实现), sb_entry(文件系统实现)之类的结构,原因是因为linux内核在实现链表,红黑树这一类基本的数据结构的时候都是最简单化的实现,如果要使用这些基本数据结构,就需要在自己定义的数据结构中包含这类最基本的数据结构。
而我们在使用中往往需要返回包含这类基本数据结构的大结构本身,这时候我们就需要用到list_entry,rb_entry这些宏的实现,而这些宏本身却都是基于一个叫container_of的宏的实现,其解释如下:


#
define container_of(ptr, type, member) ({                  \
const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
它的作用是:设ptr是某个type类型结构中的member成员变量的地址,该宏的结果是得到该type的地址。即有结构中成员变量的地址得到结构的地址。
1.ptr为物理地址,其类型和member类型一致,最终使用typeof( ((type *)0)->member )
由编译器自动返回member的类型
2.type为包含member成员的结构体
3.offsetof(type,member)为member成员在type结构体中的偏移值,大小范围0~sizeof(type)字节
(因为以0地址为type类型数据结构的起始地址)
4.ptr- offsetof()就等于包含该ptr的type结构体父变量的物理起始地址,强制转换为(type*)
.
5.
((size_t) &((TYPE *)0)->MEMBER)表示当结构TYPE为0时其成员MEMBER的地址,即位移量。

关于linux内核中的链表数据结构,推荐看一篇文章:
深入分析 Linux 内核链表》,文章链接是:
http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/
阅读(957) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~