linux内核中list的基本用法

内核链表

1 list_head 结构

为了使用链表机制,驱动程序需要包含<linux/types.h>头文件,该文件定义了如下结构体实现双向链:

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

2 链表的初始化

2.1 链表宏定义和初始化

可使用以下宏定义并初始化一个链表头部list_head,list_head 不包含数据部分。LIST_HEAD_INIT将链表头的 next 和 prev 指针都指向链表头部,从而形成一个循环结构,和下面介绍的INIT_LIST_HEAD函数一样。

#define LIST_HEAD_INIT(name) { &(name), &(name) }#define LIST_HEAD(name) \struct list_head name = LIST_HEAD_INIT(name)
2.2 链表的初始化

INIT_LIST_HEAD 是一个用于初始化链表头的函数,它将链表头的 next 和 prev 指针都指向自己,从而形成一个循环结构。

static inline void INIT_LIST_HEAD(struct list_head *list)
{WRITE_ONCE(list->next, list);WRITE_ONCE(list->prev, list);
}

如下图所示,链表头的 next 和 prev 指针都指向自己。
在这里插入图片描述

3 list_add

在链表的头部添加新链表项,以下是实现:

static inline void list_add(struct list_head *new, struct list_head *head)
{__list_add(new, head, head->next);
}static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{if (!__list_add_valid(new, prev, next))return;next->prev = new;new->next = next;new->prev = prev;WRITE_ONCE(prev->next, new);
}

以下为添加示意图,可以看出后添加节点放在链表的头部,先添加节点靠后,先进后出,后进先出,类似栈结构。
在这里插入图片描述

4 list_add_tail

在链表的尾部添加新链表项,以下是实现:


static inline void list_add_tail(struct list_head *new, struct list_head *head)
{__list_add(new, head->prev, head);
}static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{if (!__list_add_valid(new, prev, next))return;next->prev = new;new->next = next;new->prev = prev;WRITE_ONCE(prev->next, new);
}

以下为添加示意图,可以看出新添加节点放在链表的尾部,后添加节点靠,先进先出,后进后出,类似FIFO结构。
list_add_tail

5 遍历节点

5.1 list_entry

list_entry 宏通过调用 container_of 宏,从链表节点指针获取包含该节点的结构体指针。

/*** list_entry - get the struct for this entry* @ptr: 指向 &struct list_head 的指针。* @type: 包含该节点的结构体类型。* @member: 结构体中的 list_struct 名称。*/
#define list_entry(ptr, type, member) \container_of(ptr, type, member)
5.2 list_for_each

list_for_each 从链表的头部往后依次遍历(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; !list_is_head(pos, (head)); pos = pos->next)
5.3 list_for_each_entry

通过for循环,依次遍历链表中的每个节点,next方向遍历,每个节点的宿主为pos。

/*** list_for_each_entry	-	iterate over list of given type* @pos:	the type * to use as a loop cursor.* @head:	the head for your list.* @member:	the name of the list_head within the struct.*/
#define list_for_each_entry(pos, head, member)				\for (pos = list_first_entry(head, typeof(*pos), member);	\!list_entry_is_head(pos, head, member);			\pos = list_next_entry(pos, member))

a. list_first_entry 宏:

#define list_first_entry(ptr, type, member) \container_of((ptr)->next, type, member)

list_first_entry 宏用于获取链表的第一个节点的结构体指针。通过 (ptr)->next 获取到链表头部之后的第一个节点的指针,然后通过 container_of 宏获取包含该节点的整个结构体指针。

b. list_entry_is_head 宏:

#define list_entry_is_head(pos, head, member) \((pos)->member == (head))

list_entry_is_head 宏用于检查当前节点是否是链表的头部。比较 pos->member 是否等于 head,如果相等,则说明当前节点是链表的头部,即遍历结束。

c. list_next_entry 宏:

#define list_next_entry(pos, member) \list_entry((pos)->member.next, typeof(*(pos)), member)

list_next_entry 宏用于获取下一个节点的结构体指针。通过 (pos)->member.next 获取到当前节点的下一个节点的指针,然后通过 list_entry 宏获取包含该节点的整个结构体指针。

5.4 list_for_each_prev

通过for循环,依次遍历链表中的每个节点,与list_for_each_entry不同的是list_for_each_prev按照pre方向遍历,每个节点的宿主为pos。

/*** 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; !list_is_head(pos, (head)); pos = pos->prev)
5.5 删除链表

list_del
删除列表中的给定项

/*** list_del - deletes entry from list.* @entry: the element to delete from the list.* Note: list_empty() on entry does not return true after this, the entry is* in an undefined state.*/
static inline void list_del(struct list_head *entry)
{__list_del_entry(entry);entry->next = LIST_POISON1;entry->prev = LIST_POISON2;
}

list_del_init
删除列表中的给定项,如果删除后的链表可能被插入新的链表中,应该使用list_del_init,它会初始化链表的指针。

/*** list_del_init - deletes entry from list and reinitialize it.* @entry: the element to delete from the list.*/
static inline void list_del_init(struct list_head *entry)
{__list_del_entry(entry);INIT_LIST_HEAD(entry);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/380731.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧职校就业管理:开启校园招聘会新模式

在智慧职校的就业管理系统中&#xff0c;校园招聘会的出现&#xff0c;为学生们提供了一个展示自我、探寻职业道路的舞台&#xff0c;同时也为企业搭建了一座直面未来之星的桥梁。这一功能&#xff0c;凭借其独特的优势与前沿的技术&#xff0c;正在重新定义校园与职场之间的过…

react Jsx基础概念和本质

什么是jsx jsx是JavaScript和XML(HTML)的缩写&#xff0c;表示在js代码中编写HTML模板结构&#xff0c;它是react中编写UI模板的方式 const message this is message function App(){return (<div><h1>this is title</h1>{message}</div>) } jsx优…

【SpringBoot】 jasypt配置文件密码加解密

目前我们对yml配置文件中的密码都是明文显示&#xff0c;显然这不安全&#xff0c;有的程序员离职了以后可能会做一些非法骚操作&#xff0c;所以我们最好要做一个加密&#xff0c;只能让领导架构师或者技术经理知道这个密码。所以这节课就需要来实现一下。 我们可以使用jasypt…

持续集成08--Jenkins邮箱发送构建信息及测试报告

前言 在持续集成&#xff08;CI&#xff09;和持续部署&#xff08;CD&#xff09;的自动化流程中&#xff0c;及时通知团队成员关于构建的成功或失败是至关重要的。Jenkins&#xff0c;作为强大的CI/CD工具&#xff0c;提供了多种通知机制&#xff0c;其中邮件通知是最常用且有…

Java小技能:多级组织机构排序并返回树结构(包含每个层级的子节点和业务数据集合)

文章目录 引言I 实体定义1.1 部门1.2 用户组织机构中间表1.3 树状DTOII 抽取组织机构排序方法2.1 树状排序方法2.2 案例III 查询条件构建3.1 根据部门进行权限控制3.2 注入风险引言 需求: 根据组织机构进行数据授权控制,例如控制船舶、船舶设备、摄像头、港区查看权限。 一…

浅谈Canal原理

canal [kə’nl]&#xff0c;译意为水道/管道/沟渠&#xff0c;主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据 订阅 和 消费。应该是阿里云DTS&#xff08;Data Transfer Service&#xff09;的开源版本。 Canal与DTS提供的功能基本相似&#xff1a; 基于…

大模型实战—大模型赋能网络爬虫

大模型赋能网络爬虫 简单来说,网页抓取就是从网站抓取数据和内容,然后将这些数据保存为XML、Excel或SQL格式。除了用于生成潜在客户、监控竞争对手和市场研究外,网页抓取工具还可以用于自动化你的数据收集过程。 借助AI网页抓取工具,可以解决手动或纯基于代码的抓取工具的…

网络编程中的TCP和UDP

什么是TCP协议 TCP( Transmission control protocol )即传输控制协议&#xff0c;是一种面向连接、可靠的数据传输协议&#xff0c;它是为了在不可靠的互联网上提供可靠的端到端字节流而专门设计的一个传输协议。 面向连接 &#xff1a;数据传输之前客户端和服务器端必须建立连…

计算机体系结构||指令的调度和延迟分布(3)

实验3 指令的调度和延迟分布 3.1实验目的 &#xff08;1&#xff09;加深对指令调度技术的理解。 &#xff08;2&#xff09;加深对延迟分支技术的理解。 &#xff08;3&#xff09;熟练掌握用指令调度技术来解决流水线中的数据冲突的方法。 &#xff08;4&#xff09;进一…

最新版kubeadm搭建k8s(已成功搭建)

kubeadm搭建k8s&#xff08;已成功搭建&#xff09; 环境配置 主节点 k8s-master&#xff1a;4核8G、40GB硬盘、CentOS7.9&#xff08;内网IP&#xff1a;10.16.64.67&#xff09; 从节点 k8s-node1&#xff1a; 4核8G、40GB硬盘、CentOS7.9&#xff08;内网IP&#xff1a;10…

【Word】——小技巧

1.PDF相关转换word PDF转换成Word在线转换器 - 免费 - CleverPDF 2. word插入公式 1.软件推荐&#xff08;免费&#xff09; 可直接将图片&#xff0c;截屏公式转为word标准规范形式 2.网址推荐 在线LaTeX公式编辑器-编辑器 &#xff08;每天有免费使次数&#xff09; 3.…

机器学习——降维算法PCA和SVD(sklearn)

目录 一、基础认识 1. 介绍 2. 认识 “ 维度 ” &#xff08;1&#xff09;数组和Series &#xff08;2&#xff09;DataFrame 表 &#xff08;3&#xff09;图像 3. 降维思想 4. 降维步骤 二、降维算法&#xff08;PCA&#xff09; 1. PCA实现 &#xff08;1&#…

【深度学习】BeautyGAN: 美妆,化妆,人脸美妆

https://www.sysu-hcp.net/userfiles/files/2021/03/01/3327b564380f20c9.pdf 【深度学习】BeautyGAN: Instance-level Facial Makeup Transfer with Deep Generative Adversarial Network BeautyGAN: Instance-level Facial Makeup Transfer with Deep Generative Adversaria…

微服务设计原则——高性能:锁

文章目录 1.锁的问题2.无锁2.1 串行无锁2.2 无锁数据结构 3.减少锁竞争参考文献 1.锁的问题 高性能系统中使用锁&#xff0c;往往带来的坏处要大于好处。 并发编程中&#xff0c;锁带解决了安全问题&#xff0c;同时也带来了性能问题&#xff0c;因为锁让并发处理变成了串行操…

Linux openEuler_24.03部署MySQL_8.4.0 LTS安装实测验证安装以及测试连接全过程实操手册

Linux openEuler_24.03部署MySQL_8.4.0 LTS安装实测验证安装以及测试连接全过程实操手册 前言: 什么是 MySQL? MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于Oracle 公司。MySQL 是一种关系型数据库管理系统,关系型数据库将数据保存在不同的表中,…

Kafka Producer发送消息流程之消息异步发送和同步发送

文章目录 1. 异步发送2. 同步发送 1. 异步发送 Kafka默认就是异步发送&#xff0c;在Main线程中的多条消息&#xff0c;没有严格的先后顺序&#xff0c;Sender发送后就继续下一条&#xff0c;异步接受结果。 public class KafkaProducerCallbackTest {public static void mai…

JVM:JavaAgent技术

文章目录 一、Java工具的介绍二、Java Agent技术1、介绍2、静态加载模式3、动态加载模式 三、搭建java agent静态加载模式环境1、创建maven项目2、编写类和premain方法3、编写MANIFEST.MF文件4、使用maven-assembly-plugin进行打包5、创建Spring Boot应用 一、Java工具的介绍 …

C++ | Leetcode C++题解之第240题搜索二维矩阵II

题目&#xff1a; 题解&#xff1a; class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int m matrix.size(), n matrix[0].size();int x 0, y n - 1;while (x < m && y > 0) {if (matrix[x][y] targ…

HTML5大作业三农有机,农产品,农庄,农旅网站源码

文章目录 1.设计来源1.1 轮播图页面头部效果1.2 栏目列表页面效果1.3 页面底部导航效果 2.效果和源码2.1 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_4…

Spring3(代理模式 Spring1案例补充 Aop 面试题)

一、代理模式 在代理模式&#xff08;Proxy Pattern&#xff09;中&#xff0c;一个类代表另一个类的功能&#xff0c;这种类型的设计模式属于结构型模式。 代理模式通过引入一个代理对象来控制对原对象的访问。代理对象在客户端和目标对象之间充当中介&#xff0c;负责将客户端…