Linux 内核学习笔记: hlist 的理解

前言

  • 最近阅读 Linux 内核时,遇到了 hlist,这个 hlist 用起来像是普通的链表,但是为何使用 hlist,hlist 是怎么工作的?

在这里插入图片描述

  • 相关代码 hlist_add_head(&clk->clks_node, &core->clks);
/*** clk_core_link_consumer - Add a clk consumer to the list of consumers in a clk_core* @core: clk to add consumer to* @clk: consumer to link to a clk*/
static void clk_core_link_consumer(struct clk_core *core, struct clk *clk)
{clk_prepare_lock();hlist_add_head(&clk->clks_node, &core->clks);clk_prepare_unlock();
}
  • 越来越感到 Linux 内核真的是一个宝藏库,学习软件开发,阅读 Linux 内核代码,会受益匪浅。

hlist 定义

  • hlist 结构体定义所在的文件 `include\linux\types.h
struct hlist_head {struct hlist_node *first;
};struct hlist_node {struct hlist_node *next, **pprev;
};
  • 有的人理解 hlist 是 hash list 的简写,也就是 哈希链表,我不敢苟同,但 hlist 用在哈希桶上时,会由于 struct hlist_head 只有一个指针,比普通的 struct list_head 节省空间

  • 哈希表,由于哈希碰撞,即使哈希桶再大,都有可能多个数据拥有同一个哈希值,此时引入了链表,哈希值相同的元素,挂在链表上,此时由于 哈希桶的数量极大,比如 100万个,使用 struct hlist_head 会比 struct list_head 节省很大的【内存空间】

  • 由于 struct hlist_head 特殊的结构,造成 struct hlist_head 不能成为 【双向循环】链表,但是由于 struct hlist_node 有两个指针,因此可以享受 链表节点快速【插入】与【删除】的有点,这部分有点像 普通链表 struct list_head

  • struct hlist_head 只用于定义 链表的头部,链表的节点使用 struct hlist_node 定义。

  • 【重点理解】 struct hlist_node 中的 pprev 是二级指针,用于指向前一个 节点的 next,也就是前一个节点成员 next 指针的指针。这里不是 pprev = prev->next,而是 pprev= &prev->next ,一定要理解清楚,否则 pprev = prev->next 就是自身指针了,因为上一个节点的 next 就是指向下一个节点,这样获取不到上一个节点的指针。

hlist 的定义与初始化

  • 可以通过阅读 Linux 经典链表操作头文件 include\linux\list.h ,详细了解 链表的操作,比如 定义、 初始化、插入、删除、遍历等操作。

  • 如果链表嵌入在一个较大的数据结构中,双向链表的各个节点一般都是采用经典的前驱与后继相连,而通过链表成员,获取结构体的指针(地址),可以使用 container_of,比如 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)

在这里插入图片描述

  • 初始化与定义,可以直接查看 include\linux\list.h ,一般定义方法为

  • 定义 hlist 头部 struct hlist_head children;

  • 定义 hlist 节点 struct hlist_node clks_node;

  • hlist head 定义后需要初始化,可以定义时初始化,也可以手动初始化

  • 定义并初始化 static HLIST_HEAD(clk_root_list);

  • 手动在初始化函数中初始化 INIT_HLIST_HEAD(&core->clks);

hlist 插入操作

  • 由于 hlist 特殊的结构,造成 hlist 插入操作分为两种: 头部的插入 hlist_add_head ,节点的插入 hlist_add_before hlist_add_behind 两种

  • hlist_add_head 操作: 知道 hlist 头部,插入到头部后面,新插入的节点,成为第一个hlist 节点

在这里插入图片描述

  • hlist_add_before ,两个 hlist_node 节点,前面插入节点

在这里插入图片描述

  • hlist_add_behind 两个 hlist_node 节点,插入到后面,类似于 after

在这里插入图片描述

删除节点 __hlist_del

  • 由于 hlist node 节点是双向的,双重指针 pprev 可以获取到前一个节点,而 next 可以获取到后一个节点,因此像常规双向链表一样,删除操作不依赖 链表头部

在这里插入图片描述

小结

  • 深入熟悉 hlist 的操作,感觉 Linux 代码阅读起来,更熟悉了,后面抽时间自己写驱动时用起来。

  • hlist 设计很巧妙,但使用起来由于区分 链表头与链表节点,没有 list_head 操作那么简单,但是用于哈希桶结构,可以用于节省空间(链表头部节点多、链表节点少的场合)

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

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

相关文章

开题答辩ppt模板和逻辑

PPT模板和逻辑 分三个部分 1. 立题依据、研究内容 2. 技术路线、技术创新 3. 工作基础、进度安排 Part1:3页 1.1 选题背景 背景1、背景2、背景3(纵向递进式or横向并列式,每一个是一个新信息。) optional:冲突/问…

vue3项目使用pako库解压后端返回zip数据

文章目录 前言一、pako 介绍一些特点和功能:简单示例 二、vue3 实战示例1.安装后引入库安装:引用用自定义hooks 抽取共用逻辑部署小插曲 前言 外部接口返回一个图片数据是经过zip压缩的,前端需要把这个数据处理成可以显示的图片。大概思路:z…

68内网安全-域横向PTHPTKPTT哈希票据传递

今天讲PTH&PTK&PTT, PTH(pass the hash) #利用 lm 或 ntlm 的值进行的渗透测试 PTT(pass the ticket) #利用的票据凭证 TGT 进行的渗透测试 用的Kerberos 协议 PTK(pass the key) #利用的 ekeys aes256 进行的渗透测试 lm加密算法是2003以前的老版&…

vitis HLS中实现canny算法的IP核

一、前言 canny边缘检测主要用于提取图像的边缘,是最常用且有效的边缘检测算法。在AMD赛灵思提供的库函数中,使用xf::cv::Canny和xf::cv::EdgeTracing两个函数实现canny边缘提取。本文举例说明如何在vitis HLS 2023.1中实现canny算法。 二、xf::cv::Cann…

JUC常用并发工具类

JUC常用并发工具类 1、什么是JUC? JUC 就是 java.util.concurrent 包,这个包俗称 JUC,里面都是解决并发问题的一些东西,该包的位置位于 java 下 面的 rt.jar 包下面。 2、4大常用并发工具类 2.1 CountDownLatch CountDownLatch&#x…

基于Java车间工时管理系统(源码+部署文档)

博主介绍: ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精彩专栏 推荐订阅 👇🏻 不然下次找不到 Java项目精品实…

《新传奇》期刊投稿论文发表

《新传奇》杂志是经国家新闻出版总署批准、面向国内外公开发行的综合性社科期刊,由湖北省文联主管,湖北今古传奇传媒集团有限公司主办,湖北优秀期刊。本刊旨在坚守初心、引领创新,展示高水平研究成果,支持优秀学术人才…

flink中值得监控的几个指标

背景 为了维持flink的正常运行,对flink的日常监控就变得很重要,本文我们就来看一下flink中要监控的几个重要的指标 重要的监控指标 1.算子的处理速度的指标:numRecordsInPerSecond/numRecordsOutPerSecond,这有助于你了解到算子的是否正在…

如何使用 NFTScan NFT API 在 Gnosis 网络上开发 Web3 应用

Gnosis Chain 是一个兼容 EVM 的区块链,专注于快速且低成本的交易功能,采用独特的双通证模型;xDai 是一种用于交易、支付和手续费的稳定币,权益证明(PoS)保护将由 GNO 通过共识层 Gnosis Beacon Chain 提供…

【JVM】虚拟机的组成+字节码文件组成+类的生命周期

什么是JVM? JVM 本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件。 JVM的功能 1.解释和运行:对字节码文件中的指令实时的解释成机器码让计算机执行。 2.内存管理:自动为对象、方法等分配内存,自动…

【C++干货铺】STL中set和map的介绍和使用

个人主页点击直达:小白不是程序媛 C系列专栏:C干货铺 代码仓库:Gitee 目录 序列式容器 关联式容器 键值对 树形结构的关联式容器 set set的介绍 set的使用 set的模板参数列表 set的构造 ​编辑 set的容量 set的删除和查找 mult…

web等保评测需要实机查看的操作系统、服务器、数据库和应用部分

“等保测评”全称是信息安全等级保护测评。是经公安部认证的具有资质的测评机构,依据国家信息安全等级保护规范规定,受有关单位委托,按照有关管理规范和技术标准,对信息系统安全等级保护状况进行检测评估的活动。 本文陆续将遇到的…

C#中的垃圾回收(简单理解)

在C#中,当一个对象称为垃圾后任会占用内存空间,时间一长,就会导致内容空间的不足。为了清除这些无用的垃圾对象,释放一定的内容空间,C#中引用了垃圾回收机制。在这种机制下,程序员不需要过多关心垃圾对象回…

2023“SEED”第四届江苏大数据--新能源赛道 复赛Btop2总结

第一名是真的强!基本都是第一,难以撼动。 昨天新能源赛道终于落下了帷幕,真的不是一般的卷。最后的排名都到了0.0几分的差距。跟队友很辛运复赛B榜单目前进入top3的行列,下面简单总结一下赛事过程。 初赛按照天级别预测未来一周各…

函数的地址

简单介绍函数指针&#xff1a; #include <stdio.h> int add(int x,int y) { return xy; } int main() { 返回类型是整形 pf是指针变量 指向的是参数类型为&#xff08;int&#xff0c;int) 的函数 int (*pf) (int,int) add;将add的地址存入pf…

Linux iptables防火墙(一)

1.1 Linux防火墙基础 在 Internet 中&#xff0c;企业通过架设各种应用系统来为用户提供各种网络服务&#xff0c;如 Web 网站、 电子邮件系统、 FTP 服务器、数据库系统等。那么&#xff0c;如何来保护这些服务器&#xff0c;过滤企业不 需要的访问甚至是恶意的入侵呢&a…

算法设计与分析实验报告-贪心算法

校课程的简单实验报告。 算法设计与分析实验报告-递归与分治策略 算法设计与分析实验报告-动态规划算法 算法设计与分析实验报告-贪心算法 dijkstra迪杰斯特拉算法&#xff08;邻接表法&#xff09; 算法设计与分析实验报告-回溯法 算法设计与分析实验报告-分支限界法 …

Fastdeploy学习之路:Examples编译

1. 前置条件&#xff1a; 编译完Fastdeploy SDK & make install > /opt/fd_sdk 2. 进入Examples相关目录&#xff0c;然后执行&#xff1a; mkdir build & cd buildcmake .. -DFASTDEPLOY_INSTALL_DIR/opt/fd_sdk/即可生成&#xff1a; Infer_demo文件 3. 执行…

halcon字符识别结果为“\x1A”

最近在做OCR字符识别&#xff0c;遇到了点小问题&#xff0c;记录一下。 由于是项目初期&#xff0c;所以我就打算调halcon自带库去识别一下看看效果如何&#xff0c;结果分类器的结果显示为“\x1A”。如下图 百度搜了一圈没有这个解答&#xff0c;所以就在halcon帮助文档里…