/* 整理于2012.11.27 于广工大 */
在linux内核中,有大量的数据结构需要用到双循环链表,例如进程、文件、模块、页面等。若采用双循环链表的传统实现方式,需要为这些数据结构维护各自的链表,并且为每个链表都要设计插入、删除等操作函数。由于用来维持链表的next和prev指针指向对应类型的对象,因此一种数据结构的链表操作函数不能用于操作其它数据结构的链表。所以,在Linux源代码树的include/linux/list.h文件中,采用了一种(数据结构)类型无关的双循环链表实现方式。其思想是将指针prev和next从具体的数据结构中提取处理构成一种通用的“双链表”数据结构list_head,而list_head被作为一个成员嵌入到要拉链的数据结构(被称为宿主数据结构)中。这样,只需要一套通用的链表操作函数就可以将list_head成员作为“连接件”,把宿主数据结构链接起来。
linux内核的链表定义比较简单
struct list_head{
struct list_head *next,*prev;
};
list_head 结构包含两个指向list_head结构的指针,是一个双链表。但list_head没有数据域,
linux 内核链表中,不是在链表结构中包含数据,而是在数据结构中包含链表节点 list_head.
由链表节点到数据项变量是通过list_entry(ptr, type, member)宏来实现的,
ptr是指向该数据项中list_head成员的指针,
type是数据项的类型,
member为数据结构中list_head成员,
双循环链表实现方式下:
1.链表结构作为一个成员嵌入到宿主数据结构内;
2.可以将链表结构放在宿主结构内的任何地方;
3.可以为链表结构取任何名字;
4.宿主结构可以有多个链表结构。
list_head的一些常用操作(内核已经是完全的自带):
添加
内核的所有链表(包括添加、删除、移动和拼接等)操作都是针对数据结构list_head进行的。
对链表的添加操作有两种:表头添加和表尾添加。
Linux双循环链表中有一个链表头,表头添加是指添加到链表头之后,而表尾添加则是添加到链
表头的prev所指链表节点(如果是空链表,这个链表节点为链表头自身)之后。
Linux为此提供了两个接口:
static inline void list_add(struct list_head *new, struct list_head *head);
static inline void list_add_tail(struct list_head *new, struct list_head *head);
上述接口均是调用__list_add完成的<