当前位置: 首页 > news >正文

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);
}

相关文章:

linux内核中list的基本用法

内核链表 1 list_head 结构 为了使用链表机制&#xff0c;驱动程序需要包含<linux/types.h>头文件&#xff0c;该文件定义了如下结构体实现双向链&#xff1a; struct list_head {struct list_head *next, *prev; };2 链表的初始化 2.1 链表宏定义和初始化 可使用以…...

项目中无关痛痒的词句背后深层含义

项目中听上去无关痛痒的词句背后&#xff0c;深层含义有的时候并不友善。 他们说的&#xff1a;进度表有些激进 真正的意思&#xff1a;我们有麻烦了 他们说的&#xff1a;我们将在接下来的几个迭代里面弥补延误 真正的意思&#xff1a;我们还是有麻烦 他们说的&#xff1…...

DLMS协议中的高级安全(HLS)身份验证

1.四步身份验证协议 在IEC 62056-53中已说明&#xff0c;ACSE提供部分高级身份安全&#xff08;HLS&#xff09;验证服务。高级身份安全验证适用于通信通道不能提供内部安全&#xff0c;应采取防范措施以防止偷听和信息&#xff08;密码&#xff09;重现的情况。这时&#xff…...

2024“钉耙编程”杭电多校1006 序列立方(思维+前缀和优化dp)

来源 题目 Problem Description 给定长度为 N 的序列 a。 一个序列有很多个子序列&#xff0c;每个子序列在序列中出现了若干次。 小马想请你输出序列 a 每个非空子序列出现次数的立方值的和&#xff0c;答案对 998244353 取模。 你可以通过样例解释来辅助理解题意。 Input 第…...

钡铼分布式I/O系统边缘计算Modbus,MQTT,OPC UA耦合器BL206

BL206系列耦合器是一个数据采集和控制系统&#xff0c;基于强大的32 位微处理器设计&#xff0c;采用Linux操作系统&#xff0c;支持Modbus&#xff0c;MQTT&#xff0c;OPC UA协议&#xff0c;可以快速接入现场PLC、DCS、PAS、MES、Ignition和SCADA以及ERP系统&#xff0c;同时…...

防火墙--双机热备

目录 双击热备作用 防火墙和路由器备份不同之处 如何连线 双机 热备 冷备 VRRP VGMP&#xff08;华为私有协议&#xff09; 场景解释 VGMP作用过程 主备的形成场景 接口故障的切换场景 整机故障 原主设备故障恢复的场景 如果没有开启抢占 如果开启了抢占 负载分…...

机器学习 -逻辑回归的似然函数

公式解释 公式如下&#xff1a; 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简介&#xff1a; WebSocket 是一种网络传输协议&#xff0c;可在单个 TCP 连接上进行全双工通信&#xff0c;位于 OSI 模型的应用层。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455&#xff0c;后由 RFC 7936 补充规范。 WebSocket 使得客户端和服务器之间的数…...

记录工作中遇到的关于更新丢失商品超开的一个坑

场景&#xff1a; 工作中使用MybatisPlus以及Oracle进行数据库操作&#xff0c;收到RocketMQ消息开始并发分摊不同清货单的商品的批次&#xff0c;并对商品更新冻结数量。 上线后频繁出现商品超库存开票问题。&#xff08;还好是内部业务&#xff0c;人工替换批次记账即可&…...

形状之美:WebKit中CSS形状的实现与创新

形状之美&#xff1a;WebKit中CSS形状的实现与创新 在网页设计的世界里&#xff0c;CSS形状&#xff08;Shapes&#xff09;是一种革命性的特性&#xff0c;它允许开发者使用几何形状来创建复杂的布局结构。WebKit&#xff0c;作为现代浏览器的核心引擎之一&#xff0c;对CSS形…...

项目管理进阶之RACI矩阵

前言 项目管理进阶系列续新篇。 RACI&#xff1f;这个是什么矩阵&#xff0c;有什么用途&#xff1f; 在项目管理过程中&#xff0c;如Team规模超5以上时&#xff0c;则有必要采用科学的管理方式&#xff0c;满足工作需要。否则可能事倍功半。 Q&#xff1a;什么是RACI矩阵 …...

docker: No space left on device处理与迁移目录

简介&#xff1a;工作中当遇到Docker容器内部的磁盘空间已满。可能的原因包括日志文件过大、临时文件过多或者是Docker容器的存储卷已满&#xff0c;需要我们及时清理相关文件&#xff0c;并对docker的路径进行迁移。 历史攻略&#xff1a; centos&#xff1a;清理磁盘空间 …...

设计模式使用场景实现示例及优缺点(结构型模式——外观模式)

在一个繁忙而复杂的城市中&#xff0c;有一座名为“技术森林”的巨大图书馆。这座图书馆里藏着各种各样的知识宝典&#xff0c;从古老的卷轴到现的电子书籍&#xff0c;无所不包。但是&#xff0c;图书馆之所以得名“技术森林”&#xff0c;是因为它的结构异常复杂&#xff0c;…...

Artix7系列FPGA实现SDI视频编解码+UDP以太网传输,基于GTP高速接口,提供工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本博已有的以太网方案本博已有的FPGA图像缩放方案本方案的缩放应用本方案在Xilinx--Kintex系列FPGA上的应用本方案在Xilinx--Zynq系列FPGA上的应用 3、详细设计方案设计原理框图SDI 输入设备Gv8601a 均衡…...

加拿大上市药品查询-加拿大药品数据库

在加拿大&#xff0c;药品的安全性、有效性和质量是受到严格监管的。根据《食品药品法案》的规定&#xff0c;所有药品制造商必须提供充分的科学证据&#xff0c;证明其产品的安全性和有效性。为此&#xff0c;加拿大卫生部建立了一个全面的药品数据库 &#xff08;DPD) &#…...

qt自定义控件(QLabel)

先创建自定义控件类painter_label 1.自定义类必须给基类传入父窗口指针 2.重写控件中的方法 3.在UI中创建一个QLabel,右键“提升为”&#xff0c;输入类名...

阿里云国际站:海外视频安全的DRM加密

随着科技的进步&#xff0c;视频以直播或录播的形式陆续开展海外市场&#xff0c;从而也衍生出内容安全的问题&#xff0c;阿里云在这方面提供了完善的内容安全保护机制&#xff0c;适用于不同的场景&#xff0c;如在视频安全提供DRM加密。 由图可以了解到阿里云保护直播安全的…...

【Apache Doris】周FAQ集锦:第 15 期

【Apache Doris】周FAQ集锦&#xff1a;第 15 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户…...

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&#xff08;下载链接&#xff09; Staticfile CDN&#xff08;html的所有框架合集&#xff09; 直接在w3cschool里面看参考文件进行搜索自…...

SOONet与Transformer架构深度解析:提升长视频理解精度的核心技术

SOONet与Transformer架构深度解析&#xff1a;提升长视频理解精度的核心技术 最近在折腾长视频内容理解的项目时&#xff0c;遇到了一个挺头疼的问题&#xff1a;用户给一段长达几分钟甚至几十分钟的视频&#xff0c;再提一个复杂的自然语言问题&#xff0c;比如“请找出视频中…...

资源占用优化:OpenClaw在RTX4090D上并发控制策略

资源占用优化&#xff1a;OpenClaw在RTX4090D上并发控制策略 1. 为什么需要关注OpenClaw的资源占用&#xff1f; 去年冬天&#xff0c;当我第一次在RTX4090D上部署OpenClaw对接Qwen3-32B模型时&#xff0c;系统频繁崩溃的场景至今记忆犹新。原本以为24GB显存足以应对常规任务…...

**Modbus协议深度解析:基于Python的TCP通信实战与发散创新应用**在工业自动化领域,**Modbus协议

Modbus协议深度解析&#xff1a;基于Python的TCP通信实战与发散创新应用 在工业自动化领域&#xff0c;Modbus协议因其简单、稳定和开放性成为最广泛使用的串行通信标准之一。本文将从底层原理出发&#xff0c;深入剖析 Modbus TCP 的数据帧结构&#xff0c;并结合 Python 实现…...

vLLM实战:手把手教你用LLMEngine构建高效推理服务(附代码解析)

vLLM实战&#xff1a;从零构建高性能大模型推理服务的工程指南 当大语言模型从实验室走向生产环境时&#xff0c;如何实现高吞吐、低延迟的推理服务成为工程化落地的关键挑战。vLLM作为当前最受关注的开源推理框架之一&#xff0c;其核心组件LLMEngine的设计理念值得每一位AI工…...

【Python内存管理终极指南】:20年专家亲授智能体内存优化的5大核心配置步骤

第一章&#xff1a;Python智能体内存管理的底层原理与认知重构Python 的内存管理并非由开发者显式控制&#xff0c;而是通过一套高度协同的自动化机制实现——它融合了引用计数、循环垃圾回收&#xff08;GC&#xff09;与内存池&#xff08;pymalloc&#xff09;三层结构。这种…...

FastJson内存泄漏实战:我是如何用MAT工具定位到IdentityHashMap这个坑的

FastJson内存泄漏深度剖析&#xff1a;从MAT工具实战到IdentityHashMap陷阱破解 凌晨三点&#xff0c;手机突然响起刺耳的告警声——生产环境某核心服务的堆内存使用率突破95%。作为值班工程师&#xff0c;我瞬间清醒过来。这不是普通的OOM&#xff0c;而是一场持续增长的内存…...

从零开始:用ODrive和霍尔编码器打造你的第一个BLDC电机控制项目(Ubuntu环境)

从零开始&#xff1a;Ubuntu环境下用ODrive与霍尔编码器控制BLDC电机的完整指南 第一次接触无刷直流电机&#xff08;BLDC&#xff09;控制时&#xff0c;我被它高效、低噪音的特性所吸引&#xff0c;但复杂的控制逻辑让人望而却步。直到发现ODrive这个开源项目&#xff0c;它让…...

BotW-Save-Manager终极方案:深度解析《塞尔达传说:旷野之息》跨平台存档迁移技术

BotW-Save-Manager终极方案&#xff1a;深度解析《塞尔达传说&#xff1a;旷野之息》跨平台存档迁移技术 【免费下载链接】BotW-Save-Manager BOTW Save Manager for Switch and Wii U 项目地址: https://gitcode.com/gh_mirrors/bo/BotW-Save-Manager 你是否曾在Wii U上…...

2026年主流接口测试平台慢因分析与选型参考

2026年主流接口测试平台慢因分析与选型参考 核心观点摘要 2026年接口测试响应慢核心诱因可归为三类&#xff1a;工具本身并发调度能力不足、协议适配不全导致额外转码开销、缺少AI智能链路优化能力&#xff0c;多数企业接口测试效率低与工具选型不当直接相关。本次盘点覆盖当前…...

华为AR路由器VRRP配置实战:从单点故障到流量黑洞,一个实验全搞定

华为AR路由器VRRP高可用实战&#xff1a;规避单点故障与流量黑洞的深度解析 在现网架构中&#xff0c;网关设备的可靠性直接决定了整个网络的稳定性。想象一下这样的场景&#xff1a;当核心网关突然宕机&#xff0c;整个办公区的网络瞬间瘫痪&#xff0c;业务系统中断&#xff…...