博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux内核中经典链表 list_head 常见函数:初始+2个添加+删除+链表遍历 https://blog.csdn.net/qq_40334837/article/details/8106
阅读量:3920 次
发布时间:2019-05-23

本文共 2031 字,大约阅读时间需要 6 分钟。

首先找到list_head 结构体定义,kernel/inclue/linux/types.h 如下:

struct list_head {
struct list_head *next, *prev;};

然后就开始围绕这个结构开始构建链表,然后插入、删除节点 ,遍历整个链表等等,其实内核已经提供好了现成的接口,接下来就让我们进入 kernel/include/linux/list.h中:

1创建链表头LIST_HEAD(链表头仅有指针,链表节点=数据+链表头)

1、利用2个宏实现链表头创建#define LIST_HEAD_INIT(name) 	{ &(name), &(name) } #define LIST_HEAD(name) 		struct list_head name = LIST_HEAD_INIT(name)2、函数实现static inline void INIT_LIST_HEAD(struct list_head *list){
WRITE_ONCE(list->next, list); list->prev = list;}#define WRITE_ONCE(var, val) (*((volatile typeof(val) *)(&(var))) = (val))//volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。

初始化有数据的链表={数据+链表指针结构}:

在这里插入图片描述

创建宿主结构体:struct  my_task_list {
int val ; struct list_head mylist;//只包含前后指针}实例比如:struct my_task_list first_task = {
.val = 1; .mylist = LIST_HEAD_INIT(first_task.mylist);//宏替换};或者struct my_task_list my_second_task;my_second_task.val = 2;INIT_LIST_HEAD(&my_second_task.mylist);

添加节点(依旧是环状)

list_add(struct list_head *new, struct list_head *head)

传参1:struct list_head *new待插入的链表节点
传参2:struct list_head *head在该节点后面插入新节点
【向head节点后面插入节点】

先来的节点靠后,而后来的节点靠前,“先进后出,后进先出”。所以此种结构类似于 stack“堆栈”, 而 header_task就类似于内核stack中的栈顶指针esp, 它都是紧靠着最后push到栈的元素。

list_add_tail(struct list_head *new, struct list_head *head)

传参1:struct list_head *new待插入的链表节点
传参2:struct list_head *head在该节点前面插入新节点
【该函数类似于向链表尾部插入节点】

list_add_tail类似于队列尾部的放入节点

删除节点(删除后还是环状)

list_del(struct list_head *entry)//删除链表单元entry

实现:
{
  下一个节点的prev=prev
  上一个节点的next=next
}

链表遍历

从前向后遍历/** * list_for_each	-	iterate over a list * @pos:	the &struct list_head to use as a loop cursor. * @head:	the head for your list. */#define list_for_each(pos, head) \	for (pos = (head)->next; pos != (head); pos = pos->next)从后向前遍历/** * list_for_each_prev	-	iterate over a list backwards * @pos:	the &struct list_head to use as a loop cursor. * @head:	the head for your list. */#define list_for_each_prev(pos, head) \	for (pos = (head)->prev; pos != (head); pos = pos->prev)

而且,list.h 中也提供了list_replace( 节点替换) list_move(节点移位) ,翻转,查找等接口,这里就不在一一分析了。

转载地址:http://pyhrn.baihongyu.com/

你可能感兴趣的文章
模式10. 观察者模式-Java
查看>>
剑指 Offer 11. 旋转数组的最小数字
查看>>
剑指 Offer 07. 重建二叉树
查看>>
剑指 Offer 09. 用两个栈实现队列
查看>>
模式12.状态模式-Java
查看>>
Volatile-1.保证可见性
查看>>
Volatile-2.不保证原子性
查看>>
Volatile-3.禁止指令重排
查看>>
JMM (Java内存模型)
查看>>
剑指 Offer 13. 机器人的运动范围
查看>>
Leetcode 43. 字符串相乘
查看>>
剑指 Offer 24. 反转链表
查看>>
剑指 Offer 25. 合并两个排序的链表
查看>>
剑指 Offer 26. 树的子结构
查看>>
剑指 Offer 27. 二叉树的镜像
查看>>
剑指 Offer 28. 对称的二叉树
查看>>
剑指 Offer 29. 顺时针打印矩阵
查看>>
剑指 Offer 30. 包含min函数的栈
查看>>
剑指 Offer 31. 栈的压入、弹出序列
查看>>
剑指 Offer 32 - I. 从上到下打印二叉树
查看>>