前言
内核中链表是比较简单的数据结构,通过两个指针元素实现双向链表。
链表相比其他数据结构的优点是不占用连续的内存,可以动态的插入和删除节点。
比较简单的链表
链表中前后指针元素和数据元素在同一个结构体中。通过指针可以直接找到数据。
单向链表
1 | struct list_element { |
双向链表
1 | struct list_element { |
linux 内核中双向链表的实现
linux 内核中的链表数据结构中存放的是链表节点,而不是数据节点,通过链表指针来查找数据元素。
存放数据的结构体
1 | struct fox { |
存放链表指针的结构体
1 | struct list_head { |
container_of()宏
链表数据结构中只存放 list_head 类型的数据结构,那么怎么通过 list_head 元素得到所在的数据呢,通过container_of()宏,使用 list_head 的地址已经数据元素的偏移量来获取数据内容
1 | #define container_of(ptr, type, member) |
上述内核代码在 <linux/list.h> 中声明
内核中链表的使用
下面是内核中一些已经定义好的增删便利的函数。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21static LIST_HEAD(fox_list);
list_add(struct list_head *new, struct list_head *head)
list_add(&f->list, &fox_list);
list_add_tail(struct list_head *new, struct list_head *head)
list_del(struct list_head *entry)
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
list_move(struct list_head *list, struct list_head *head)
struct list_head *p;
struct fox *f;
list_for_each(p, &fox_list) {
/* f points to the structure in which the list is embedded */
f = list_entry(p, struct fox, list);
}
自己手写的链表实验
1 | #include <stddef.h> |