Chinaunix首页 | 论坛 | 博客
  • 博客访问: 480918
  • 博文数量: 76
  • 博客积分: 5196
  • 博客等级: 大校
  • 技术积分: 1414
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-10 18:43
个人简介

转了个圈,又回来了

文章分类

全部博文(76)

文章存档

2013年(1)

2011年(8)

2010年(9)

2009年(22)

2008年(36)

我的朋友

分类: LINUX

2009-12-26 15:46:24

linux-链表
在看linux内核或者由linux提供的一些代码中,经常会遇到LIST_HEAD、INIT_LIST_HEAD等宏定义,以及一些如list_for_each、list_entry等函数。下面我介绍下常用的几个宏定义以及函数的意义。
 
1.struct list_head
在linux中用的是双向循环链表,定义的结构如下:
struct list_head
{
    struct list_head *next, *prev;
}
注意定义的这个链表节点中是没有数据域的,在linux内核中不是链表结构中包含数据域,而是在数据结构中内嵌链表节点。这个和linux内核中的KObjet等数据结构一样都是内嵌的。
 
2.初始化linux链表
初始化一个链表就是声明一个节点,让这个节点的prev域和next域都指向它自身。有两种方法:
(1):LIST_HEAD(name);

#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
 
声明一个节点name ,让这个节点的prev域和next域都指向它自身的地址。
 
(2):INIT_LIST_HEAD(ptr);
 
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
 
以上两个没有区别,就是在使用INIT_LIST_HEAD之前要先申明一个list_head变量ptr。
 
2.遍历一个链表
(1)list_for_each;
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
 
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
list_for_each()有prefetch()prefetch() prefetch()用于预取以提高遍历速度,而__list_for_each()无prefetch()用于简单的表的遍历.
(2)list_for_each_safe
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
这个主要是在遍历的过程中,要删除这个节点是用到。如果在list_for_each中调用list_del(pos)(将pos的前后指针指向undefined state)panic,list_del_init(pos)(将pos前后指针指向自身)导致死循环。
 
注意list_for_each和list_for_each_safe就是一个for循环,使用的时候注意如果在循环体里面有删除节点是用list_for_each_safe,没有得时候就用list_for_each.
 
3.list_entry()函数
list_entry函数用于根据链表指针找到包含这个链表指针的数据结构体。
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
 
container_of见文章 《LINUX基础-container_of》
 
4.list_for_each_entry
一般来讲用list_for_each循环遍历以后,就要调用list_entry来获得数据结构体。list_for_each_entry就是上面两个的综合。
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, t ypeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))



 
阅读(1891) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~