linux内核链表的实现

本文会记录一些linux内核实现中使用到的一些小技巧,工具等等,会根据学习进度不定时更新本文......
双向循环链表
第一个想写的是linux的双向循环链表(写这个的原因是因为最近学习epoll的内核代码实现,进而需要了解linux的等待队列,这其中也用到了双向循环链表,稍后也会分析linux的等待队列)
linux的双向循环链表之于传统的双向循环链表,其优点是:将其从具体的数据结构中提取出来构成一种通用的循环链表实现,在linux中表现形式为:
struct list_head { 
struct list_head * prev , * next; 

其常见的使用方法为:若要定义某种特定类型的数据结构的双向循环链表,只需要在结构中包含该struct list_head ,就可以将各个对象链接起来;当对数据结构进行操作(增,删......)的时候,只需要设计针对struct list_head这种通用结构的通用接口即可,不用针对每种具体对象设计不同的接口
典型的结构如下(暂时不会作图,先盗用了等待队列的实现图):

一般实现一个具体对象的双向循环链表的时候会有一个头节点,只含有struct list_head(假设为struct list_head head;),没有具体对象的信息,若要判断是否队列为空,则只需判断head->prev==head (head->netx == head);具体实现如下:
static inline int list_empty(const struct list_head * head){ 
return head->next == head; 
}

另一个比较很重要的操作就是通过list_head成员获取宿主对象的指针了,这个主要用到了宏:offsetof,container_of
#define offsetof(s,m) (size_t)&(((s *)0)->m) 
//s为结构体,m为结构体中的成员,将地址0强制转换为对应的结构体类型,
//而成员m所在的地址减去结构体起始位置即为m在结构体中偏移量,
//此处基地址为0,则成员m所在地址即为偏移量 

#define container_of(ptr, type, member) ({ / 
const typeof( ((type *)0)->member ) *__mptr = (ptr); / 
(type *)( (char *)__mptr - offsetof(type,member) );}) 
//作用:获得某成员所在结构体的入口地址 
//实现:type为结构题的类型,member为结构体中的一个成员,
//   ptr为指向成员member所属变量类型的一个变量的指针
// 故技重施,(type *)0将地址0强制转换为type结构体类型的地址,
//   typeof( ((type *)0->member)获得了member的类型,
//   接着typeof( ((type *)0->member) * __mptr申明了一个该类型的变量并初始化为ptr的地址;
//   (char *)__mptr将刚刚的地址转换为char* ,offsetof计算出了member成员在结构体中的偏移量,
//   __mptr减去这个偏移刚好就是结构体的起始地址,然后用(type *)强制转换为相应的指针 

有关等待队列的数据结构稍后补充......
本文出自 "流离and逍遥" 博客,请务必保留此出处http://liulixiaoyao.blog.51cto.com/1361095/535427

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值