博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

用今天的眼睛来看明天-jamesr

继续坚持使用Linux
   jamesr.cublog.cn
关于作者  
姓名:阮贝鸿
职业:学生
年龄:18
位置:中国,宁波
个性介绍:

我的分类  




Linux 内核的链表真是精辟!
一直听人说Linux内核中的链表是一个C实现的链表的典型,一直没有去了解。
最近看了一点点内核代码,看到链表的使用,觉得看不大懂。于是上网搜索相关文章,得出一个结论:Linux 内核的链表真是精辟!

传统的链表都是数据和指针装在一个节点里:
struct node
{
    type data;
    struct node *prev,*next;
};
而内核链表把指针独立出来,做成节点,在被含有数据的entry包含:
struct list_head
{
    struct list_head *prev,*next;
};

struct entry
{
    struct list_head* list;
    type data;
};

用节点做为遍历的iterator,来处理数据。这样做很好得解决了一个问题,那就是如何使一个链表的实现能独立于数据。不同是数据type就不同,按以往的方式,一种数据就得实现一套链表处理。C++中用模板来解决,而内核链表是C,用这种方法来解决。

数据在节点以外,那怎么访问节点对应的数据呢?
内核链表提供了这个宏:
#define list_entry(ptr, type, member) container_of(ptr, type, member)

而container_of的定义是:
#define container_of(ptr, type, member) ({ \
 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
 (type *)( (char *)__mptr - offsetof(type,member) );})

offsetof是我们熟悉的:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

利用list_head在entry中的位置与list_head的指针,反推出entry的位置。
使用list_entry的方法:
如定义了
struct entry
{
    struct list_head* list;
    int data;
}myentry;
调用
struct entry* return_value=list_entry(list,struct entry,list);

return_value==&myentry;


 发表于: 2008-06-05,修改于: 2008-06-05 16:10 已浏览407次,有评论2条 推荐 投诉

  网友评论
  seaway 时间:2008-09-02 12:27:43 IP地址:218.28.121.★
kernel的这个双向链表实现的确实赞。完美实现了数据结构代码复用

  natea_3 时间:2008-09-10 08:47:40 IP地址:222.92.8.★
呵呵,那个container_of的宏很常用。
写设备驱动的时候,就常用内嵌的子设备指针来反推出设备的指针:)


  发表评论



Copyright © 2001-2006 ChinaUnix.net All Rights Reserved

感谢所有关心和支持过ChinaUnix的朋友们
页面生成时间:2.45393

京ICP证041476号