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结构。
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);
}
相关文章:
linux内核中list的基本用法
内核链表 1 list_head 结构 为了使用链表机制,驱动程序需要包含<linux/types.h>头文件,该文件定义了如下结构体实现双向链: struct list_head {struct list_head *next, *prev; };2 链表的初始化 2.1 链表宏定义和初始化 可使用以…...
项目中无关痛痒的词句背后深层含义
项目中听上去无关痛痒的词句背后,深层含义有的时候并不友善。 他们说的:进度表有些激进 真正的意思:我们有麻烦了 他们说的:我们将在接下来的几个迭代里面弥补延误 真正的意思:我们还是有麻烦 他们说的࿱…...
DLMS协议中的高级安全(HLS)身份验证
1.四步身份验证协议 在IEC 62056-53中已说明,ACSE提供部分高级身份安全(HLS)验证服务。高级身份安全验证适用于通信通道不能提供内部安全,应采取防范措施以防止偷听和信息(密码)重现的情况。这时ÿ…...
2024“钉耙编程”杭电多校1006 序列立方(思维+前缀和优化dp)
来源 题目 Problem Description 给定长度为 N 的序列 a。 一个序列有很多个子序列,每个子序列在序列中出现了若干次。 小马想请你输出序列 a 每个非空子序列出现次数的立方值的和,答案对 998244353 取模。 你可以通过样例解释来辅助理解题意。 Input 第…...
钡铼分布式I/O系统边缘计算Modbus,MQTT,OPC UA耦合器BL206
BL206系列耦合器是一个数据采集和控制系统,基于强大的32 位微处理器设计,采用Linux操作系统,支持Modbus,MQTT,OPC UA协议,可以快速接入现场PLC、DCS、PAS、MES、Ignition和SCADA以及ERP系统,同时…...
防火墙--双机热备
目录 双击热备作用 防火墙和路由器备份不同之处 如何连线 双机 热备 冷备 VRRP VGMP(华为私有协议) 场景解释 VGMP作用过程 主备的形成场景 接口故障的切换场景 整机故障 原主设备故障恢复的场景 如果没有开启抢占 如果开启了抢占 负载分…...
机器学习 -逻辑回归的似然函数
公式解释 公式如下: L ( θ ) ∏ i 1 m P ( y i ∣ x i ; θ ) ∏ i 1 m ( h θ ( x i ) ) y i ( 1 − h θ ( x i ) ) 1 − y i L(\theta) \prod_{i1}^m P(y_i | x_i; \theta) \prod_{i1}^m (h_\theta(x_i))^{y_i} (1 - h_\theta(x_i))^{1 - y_i} L(θ)i1∏…...
go 实现websocket以及详细设计流程过程,确保通俗易懂
websocket简介: WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455,后由 RFC 7936 补充规范。 WebSocket 使得客户端和服务器之间的数…...
记录工作中遇到的关于更新丢失商品超开的一个坑
场景: 工作中使用MybatisPlus以及Oracle进行数据库操作,收到RocketMQ消息开始并发分摊不同清货单的商品的批次,并对商品更新冻结数量。 上线后频繁出现商品超库存开票问题。(还好是内部业务,人工替换批次记账即可&…...
形状之美:WebKit中CSS形状的实现与创新
形状之美:WebKit中CSS形状的实现与创新 在网页设计的世界里,CSS形状(Shapes)是一种革命性的特性,它允许开发者使用几何形状来创建复杂的布局结构。WebKit,作为现代浏览器的核心引擎之一,对CSS形…...
项目管理进阶之RACI矩阵
前言 项目管理进阶系列续新篇。 RACI?这个是什么矩阵,有什么用途? 在项目管理过程中,如Team规模超5以上时,则有必要采用科学的管理方式,满足工作需要。否则可能事倍功半。 Q:什么是RACI矩阵 …...
docker: No space left on device处理与迁移目录
简介:工作中当遇到Docker容器内部的磁盘空间已满。可能的原因包括日志文件过大、临时文件过多或者是Docker容器的存储卷已满,需要我们及时清理相关文件,并对docker的路径进行迁移。 历史攻略: centos:清理磁盘空间 …...
设计模式使用场景实现示例及优缺点(结构型模式——外观模式)
在一个繁忙而复杂的城市中,有一座名为“技术森林”的巨大图书馆。这座图书馆里藏着各种各样的知识宝典,从古老的卷轴到现的电子书籍,无所不包。但是,图书馆之所以得名“技术森林”,是因为它的结构异常复杂,…...
Artix7系列FPGA实现SDI视频编解码+UDP以太网传输,基于GTP高速接口,提供工程源码和技术支持
目录 1、前言工程概述免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本博已有的以太网方案本博已有的FPGA图像缩放方案本方案的缩放应用本方案在Xilinx--Kintex系列FPGA上的应用本方案在Xilinx--Zynq系列FPGA上的应用 3、详细设计方案设计原理框图SDI 输入设备Gv8601a 均衡…...
加拿大上市药品查询-加拿大药品数据库
在加拿大,药品的安全性、有效性和质量是受到严格监管的。根据《食品药品法案》的规定,所有药品制造商必须提供充分的科学证据,证明其产品的安全性和有效性。为此,加拿大卫生部建立了一个全面的药品数据库 (DPD) &#…...
qt自定义控件(QLabel)
先创建自定义控件类painter_label 1.自定义类必须给基类传入父窗口指针 2.重写控件中的方法 3.在UI中创建一个QLabel,右键“提升为”,输入类名...
阿里云国际站:海外视频安全的DRM加密
随着科技的进步,视频以直播或录播的形式陆续开展海外市场,从而也衍生出内容安全的问题,阿里云在这方面提供了完善的内容安全保护机制,适用于不同的场景,如在视频安全提供DRM加密。 由图可以了解到阿里云保护直播安全的…...
【Apache Doris】周FAQ集锦:第 15 期
【Apache Doris】周FAQ集锦:第 15 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目! 在这个栏目中,每周将筛选社区反馈的热门问题和话题,重点回答并进行深入探讨。旨在为广大用户…...
verilog实现ram16*8 (vivado)
module ram_16x2 (input clk, // 时钟信号input we, // 写使能input en, // 使能信号input [3:0] addr, // 地址线input [1:0] datain, // 输入数据线output reg [1:0] dataout // 输出数据线 );// 定义存储器数组reg [1:0] mem [15:0];always (posedge…...
框架使用及下载
Bootstrap5 安装使用 | 菜鸟教程 (runoob.com) https://github.com/twbs/bootstrap/releases/download/v5.1.3/bootstrap-5.1.3-dist.zip(下载链接) Staticfile CDN(html的所有框架合集) 直接在w3cschool里面看参考文件进行搜索自…...
通用图形处理器设计GPGPU基础与架构(四)
一、前言 本文将介绍GPGPU中线程束的调度方案、记分牌方案和线程块的分配与调度方案。 二、线程束调度 在计算机中有很多资源,既可以是虚拟的计算资源,如线程、进程或数据流,也可以是硬件资源,如处理器、网络连接或 ALU 单元。调…...
会Excel就会sql?
如果你熟悉Excel,理解SQL(结构化查询语言,Structured Query Language)会相对容易,因为它们在某些功能上有着相似之处。SQL主要用于管理和操作数据库中的数据,而Excel则是电子表格软件,用于数据的组织、分析和可视化。下面我会用Excel的视角来帮你理解SQL的基本概念。 数…...
MyBatis-Plus的几种常见用法
MyBatis-Plus 提供了丰富的高级用法,可以简化开发,提高效率。以下是一些常见的可能会被忽略的用法示例。 1. 乐观锁 乐观锁用于避免在并发环境下数据更新冲突。MyBatis-Plus 通过注解和版本字段实现乐观锁。 示例: 在实体类中添加版本字段…...
【LeetCode】day15:110 - 平衡二叉树, 257 - 二叉树的所有路径, 404 - 左叶子之和, 222 - 完全二叉树的节点个数
LeetCode 代码随想录跟练 Day15 110.平衡二叉树257.二叉树的所有路径404.左叶子之和222.完全二叉树的节点个数 110.平衡二叉树 题目描述: 给定一个二叉树,判断它是否是 平衡二叉树 平衡二叉树的定义是,对于树中的每个节点,其左右…...
【网络安全的神秘世界】Error:Archives directory /var/cache/apt/archives/partial is missing.
🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 ✨问题描述 在kali中想要安装beef-xss软件包时,发生如下报错: Error: Archives directory /var/cac…...
网络编程中的TCP和UDP
什么是TCP协议 TCP( Transmission control protocol )即传输控制协议,是一种面向连接、可靠的数据传输协议,它是为了在不可靠的互联网上提供可靠的端到端字节流而专门设计的一个传输协议。 面向连接 :数据传输之前客户端和服务器端必须建立连…...
基于python的时空地理加权回归(GTWR)模型
一、时空地理加权回归(GTWR)模型 时空地理加权回归(GTWR)模型是由美国科罗拉多州立大学的Andy Liaw、Stanley A. Fiel和Michael E. Bock于2008年提出的一种高级空间统计分析方法。它是在传统地理加权回归(GWR…...
什么是单例模式,有哪些应用?
目录 一、定义 二、应用场景 三、6种实现方式 1、懒汉式,线程不安全。 2、懒汉式,线程安全 3、双检锁/双重校验锁(DCL,即 double-checked locking) 4、静态内部类方式-------只适用于静态域 5、饿汉式 6、枚举…...
adb命令操作手机各种开关
打开iqoo手机热点设置 adb shell am start -n com.android.settings/com.android.settings.Settings$\VivoTetherSettingsActivity蓝牙模块 检查蓝牙状态的ADB命令 检查蓝牙开关状态 adb shell settings get global bluetooth_on开启和关闭蓝牙 使用Intent操作蓝牙…...
【分布式存储系统HDFS】架构和使用
分布式存储系统HDFS:架构和使用 目录 引言HDFS简介HDFS的架构 NameNodeDataNodeSecondary NameNode HDFS的工作原理 数据读写流程数据冗余与恢复 HDFS的安装和配置 环境准备HDFS安装步骤HDFS配置文件启动HDFS HDFS的使用 基本命令HDFS Shell操作Java API操作 HDFS…...
怎样做旅游网站/美国今天刚刚发生的新闻
IO的分类 IO IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。 IO流的简单分类 按照流的流向分,可以分为输入流和输出流;按照操作单元划分,可以划分为字节流和字符流;按照流的角色划分为节点…...
直播带货系统/对网站的建议和优化
本文研究全球及中国市场身份和访问管理(IAM)软件现状及未来发展趋势,侧重分析全球及中国市场的主要企业,同时对比北美、欧洲、中国、日本、东南亚和印度等地区的现状及未来发展趋势。 根据QYR(恒州博智)的统…...
专业网站建设市场/友链
本题就是求半交平面的交包含哪些直线,而且有点特殊(一般的半交平面用双端队列,因为可能转到最开始的直线,但本题不会,所以只需要一端操作就行了)。 1 /**************************************************…...
网站建设 行业资讯/谷歌搜索引擎免费入口 台湾
Background 最近无意间翻到了一个b站视频, 讲了一套类似yjingo理论的视频, 而且和我自己的学习理论差不多。 但是作者提到了一个进步, 他对进步的理解非常深刻, 其实我也知道他说进步就是在挑战区做工作, 但是作者是怎…...
网站做记录访客/百度手机应用市场
最近在做MIS管理系统中,对于数据列表展示前面要加上一个序号,全选等功能(本篇文章只解决在DataGrid前加序号问题);从网上也看到有 朋友对这方面的功能做了一些讲解,其功能都是一样,也没有什么好说;关键在于…...
发明迷网站豆渣做豆腐/seo关键词排名软件流量词
最近一位想跳槽大厂的老程序员朋友面试了几家发现:6年前面试最常问的并且可以顺利拿到高薪的技能是 Dubbo ,2年前面试,只要你简历上有 Spring Cloud 项目的相关经验,肯定会打动面试官,现在呢?简历上有Dubbo和简单的Spr…...