一,内核链表定义
言以蔽之,内核链表就是个带头结点的循环双链表。
普通的链表是将next指针定义成为与该结构体一样的类型,这样做通用性不好。与普通的链表的定义和使用方式不一样,内核的链表定义成为了一种通用的结构:
双链表多了一个指针域。分为前驱(prev)和后继(next)指针
struct list_head {
struct list_head *next, *prev;
};
二,链表操作
1 初始化链表
宏创建一个链表头结点,并用 LIST_HEAD_INIT 宏对头结点进行赋值,使得头结点的前驱和后继指向自己。INIT_LIST_HEAD 函数对链表进行初始化,使得前驱和后继指针指针指向头结点。
2 链表的遍历
使用 list_for_each 宏来对链表进行遍历所有的元素。
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
举例:
list_for_each(pos, &head)
{
tmp = list_entry(pos, struct student, list);
printf("%d ", tmp->age);
}
puts("\n");
3插入链表节点
1. 首先创建一个链表头:listHead
LIST_HEAD(listHead);
2. 然后再创建第一个链表节点:
struct my_data_list first_data =
{
.val = 1,
.list = LIST_HEAD_INIT(first_data.list),
};
3. 接着 把这个节点插入到 listHead 后
list_add(&frist_data.list, &listHead);
4. 紧接着我们再创建第二个节点:
struct my_data_list second_data =
{
.val = 2,
/* 也可以调用接口 初始化*/
.list = LIST_HEAD_INIT(second_data.list),
};
list_add(&second_data.list, &listHead);