Linux内核链表实现过程内核链表实现过程
本文讲解Linux内核链表实现的过程,说了链表的定义及初始化宏定义、插入操作和删除操作等内容,详细看下
面
关于双链表实现,一般教科书上定义一个双向链表节点的方法如下:
复制代码 代码如下:
struct list_node{
stuct list_node *pre;
stuct list_node *next;
ElemType data;
}
即一个链表节点包含:一个指向前向节点的指针、一个指向后续节点的指针,以及数据域共三部分。
但查看linux内核代码中的list实现时,会发现其与教科书上的方法有很大的差别。
来看看linux是如何实现双链表。
双链表节点定义
复制代码 代码如下:
struct list_head {
struct list_head *next, *prev;
};
发现链表节点中根本就没有数据域,这样的链表有什么用?linux内核中定义这样的链表原因何在?
这是因为linux中是通过独立定义一个链表结构,并在结构体中内嵌一个链表节点来实现链表结构的。这样有一个好处就是能
达到链表与结构体分离的目的。如此一来,我们构建好一个链表后,其结构示意图如下:
链表的定义及初始化宏定义:链表的定义及初始化宏定义:
复制代码 代码如下:
#define LIST_HEAD_INIT(name){&(name),&(name)}
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr);\
} while (0)
LIST_HEAD(name)宏用来定义一个链表头,并使他的两个指针都指向自己。我们可以在程序的变量声明处,直接调用
LIST_HEAD(name)宏,来定义并初始化一个名为name的链表。也可以先声明一个链表,然后再使用INIT_LIST_HEAD来初始
化这个链表。
也即:
复制代码 代码如下:
LIST_HEAD(mylist);
与
struct list_head mylist;
INIT_LIST_HEAD(&mylist);
是等价的。
插入操作插入操作
复制代码 代码如下:
/*仅供内部调用
* Insert a new entry between two known consecutive entries.
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;