善用Linux内核中的各种数据结构和算法

2023-11-07

1、介绍

在数据结构和算法一文中经常就信手拈来一些基本数据结构和算法,如链表、队列、栈、二叉树等等,但是在C的标准库中并没有自带这些,C++通过STL、类程序库等等会带这些,那么在嵌入式开发里面怎么快速方便使用这些数据结构和算法咧?答案就是从Linux内核或者模块程序里去学习这些算法,Linux里面的实现是经过了千锤百炼的,在标准化、复杂度和效率上应该比一般人写的好得多,所以先去学习下大神们的代码,再通过总结来实现自己的一套,后面在一些非Linux系统的程序中就可以直接使用这些轮子了。本文总结记录嵌入式C里面经常要用到的数据结构和算法。这些算法的参考链接为:

https://linux.cn/article-2317-1.html        各种算法链接

内核队列实现:https://blog.csdn.net/yusiguyuan/article/details/19905427 

环形队列的ABA问题:https://www.cnblogs.com/shines77/p/4200127.html

无锁环形队列实现:https://www.cnblogs.com/lvdongjie/p/9679265.htmlhttps://github.com/dodng/fast_ring_queue

ringbuffer实现:https://github.com/XinLiGH/RingBuffer/tree/master/RingBuffer/RingBuffer

CAS:https://blog.csdn.net/stpeace/article/details/81150393

锁与共享变量:https://blog.csdn.net/yanluandai1985/article/details/82686486

 

       要建立一个真正无锁的数据结构来操作需要借助于系统的CAS操作, CAS是compare and swap,   简单来说就是,在写入新值之前, 读出旧值, 当且仅当旧值与存储中的当前值一致时,才把新值写入存储。__sync_bool_compare_and_swap是可供程序员调用的接口。

      加锁是一种悲观的策略,它总是认为每次访问共享资源的时候,总会发生冲突,所以宁愿牺牲性能(时间)来保证数据安全。无锁是一种乐观的策略,它假设线程访问共享资源不会发生冲突,所以不需要加锁,因此线程将不断执行,不需要停止。一旦碰到冲突,就重试当前操作直到没有冲突为止。无锁的策略使用一种叫做比较交换的技术(CAS Compare And Swap)来鉴别线程冲突,一旦检测到冲突产生,就重试当前操作直到没有冲突为止。

CAS核心算法:执行函数:CAS(V,E,N)   

V表示准备要被更新的变量       

E表示我们提供的 期望的值

N表示新值 ,准备更新V的值

由于CAS操作属于乐观派,它总是认为自己能够操作成功,所以操作失败的线程将会再次发起操作,而不是被OS挂起。所以说,即使CAS操作没有使用同步锁,其它线程也能够知道对共享变量的影响。

        因为其它线程没有被挂起,并且将会再次发起修改尝试,所以无锁操作即CAS操作天生免疫死锁。

        另外一点需要知道的是,CAS是系统原语,CAS操作是一条CPU的原子指令,所以不会有线程安全问题。
 

2、无锁环形队列

内核中关于队列定义的头文件位于:<linux/kfifo.h> include/linux/kfifo.h,头文件中定义的函数的实现位于:kernel/kfifo.c,

内核队列编程需要注意的是:

  • 队列的size在初始化时,始终设定为2的n次方
  • 使用队列之前将队列结构体中的锁(spinlock)释放

kfifo 是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现;它提供一个无边界的字节流服务,最重要的一点是,它使用并行无锁编程技术,即当它用于只有一个入队线程和一个出队线程的场情时,两个线程可以并发操作,而不需要任何加锁行为,就可以保证kfifo的线程安全。

采用数组实现无锁环形队列没有ABA问题,用链表实现会有ABA问题。

2.1 环形队列适用场景

一般应用于需要高效且频繁进行多线程通信传递数据的场景,例如:linux捕包、发包等等,(linux系统中对PACKET_RX_RING和PACKET_TX_RING的支持实质就是内核实现的一种环形队列)。

2.2 ringbuffer原理

链表和线性表都是可以的,但几乎都用线性表实现,比链表快很多,原因也是显而易见的,因为访问链表需要挨个遍历。

 上面定义的是一个容量(Capacity)为8的RingBuffer,一般RingBuffer的容量取为2的N次幂,这样计算索引时可以使用 index = sequence & mask; (其中mask = capacity - 1;) 以提高代码效率。其中索引表示数组的下标,数组中保存的数据是A, B, C, D, Empty等。Head 表示队列的头指针(即首个可以压入数据的位置),Tail 表示队列的尾指针(即首个可以弹出数据的位置),Head、Tail都是以序号的形式存在,且是单调递增的,且可以大于等于Capacity(8),如果Head = 8 时表示数组的第一个元素(因为回转回来了,即 index = 8 & (8 - 1) = 8 & 7 = 0;),Head = 9 表示的其实是存储在数组的第二个元素。

队列内元素的实际长度为:Length = Head - Tail,其中 (Head - Tail) 必须 <= Capacity(最大容量),因为这个时候表示队列已经满了,如果(Head - Tail) = 0,则代表队列为空。为什么叫 RingBuffer,就是因为它是一个环,游标到了数组的尾部又回转到数组的头部。

判断队列是否已满的逻辑为:队列实际长度 >= 队列最大容量,即:if ((head - tail) >= capacity) return -1; 由于 mask = capacity - 1,还可以简化为:if ((head - tail) > mask) return -1; 。

2.3 代码实现

 

3、栈

 

 

 


 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

善用Linux内核中的各种数据结构和算法 的相关文章

  • 数据库多维迭代算法

    关键词 数据库 迭代 递归 多维 一 两种传统的数据库迭代结构算法 对于数据库的迭代结构 有两种传统的算法 递归算法和边界算法 比如对于下面图1的结构 图1 递归算法的数据结构如表1所示 节点id 节点值 父节点id 1 1111 2 3
  • 《Linux From Scratch》第三部分:构建LFS系统 第六章:安装基本的系统软件- 6.29. Coreutils-8.23...

    Coreutils 软件包包含用于显示和设置基本系统特性的工具 大概编译时间 2 5 SBU 需要磁盘空间 193 MB 6 29 1 安装 Coreutils POSIX 要求 Coreutils 中的程序即使在多字节语言环境也能正确识别
  • BP神经网络与Python实现

    人工神经网络是一种经典的机器学习模型 随着深度学习的发展神经网络模型日益完善 联想大家熟悉的回归问题 神经网络模型实际上是根据训练样本创造出一个多维输入多维输出的函数 并使用该函数进行预测 网络的训练过程即为调节该函数参数提高预测精度的过程
  • Hash table and application in java

    查找的效率取决于在查找是比较的次数 次数越少效率越高 反之越低 最理想的情况是无需比较 一次存取便能找到所查找的记录 根据对应关系f找到给定值K的像f K hash function 应运而生 由此思想建的表称为hash table 集合h
  • PCL—低层次视觉—点云分割(RanSaC)

    点云分割 点云分割可谓点云处理的精髓 也是三维图像相对二维图像最大优势的体现 不过多插一句 自Niloy J Mitra教授的Global contrast based salient region detection出现 最优分割到底鹿死
  • 链表和线性表的优缺点

    链表和线性表的优缺点 作为我们最先接触的两个数据结构 链表和线性表的优缺点都较为明显 并且二者互相补足 文章目录 链表和线性表的优缺点 线性表 线性表的组成 线性表的缺点 线性表的优点 链表 链表的组成 链表的优点 链表的缺点 总结 线性表
  • 用 Java 实现的八种常用排序算法

    八种排序算法可以按照如图分类 前置知识 1 算法稳定性 在一个序列中 能保证两个相等的数 经过排序之后 其在序列的前后位置顺序不变 A1 A2 排序前 A1 在 A2 前面 排序后 A1 还在 A2 前面 2 时间复杂度 时间复杂度是用于衡
  • 数据结构与算法学习总结(六)——字符串的模式匹配算法

    基本概念 字符串是一种特殊的线性表 即元素都是 字符 的线性表 字符是组成字符串的基本单位 字符的取值依赖于字符集 例如二进制的字符集为0 1 则取值只能为 0 1 再比如英语语言 则包括26个字母外加标点符号 例如 abcde 就是一个字
  • 如何根据链表节点数据大小对链表节点进行排序

    对链表排序有两种方法 1 比较了两个节点的大小后 对指针进行改变 从而交换节点的顺序 2 比较了两个节点的大小后 只交换数据域 而不改变指针 从而交换节点的顺序 第二种办法比较简单 本文主要对第二种方法进行讲解 链表节点排序算法 采用 冒泡
  • 『Python基础-15』递归函数 Recursion Function

    什么是递归函数 一种计算过程 如果其中每一步都要用到前一步或前几步的结果 称为递归的 用递归过程定义的函数 称为递归函数 例如连加 连乘及阶乘等 凡是递归的函数 都是可计算的 即能行的 递归就是一个函数在它的函数体内调用它自身 编程语言中的
  • 数据结构——计算节点个数和二叉树高度(C语言版)

    摘自 数据结构 计算节点个数和二叉树高度 C语言版 作者 正弦定理 发布时间 2020 12 12 23 27 09 网址 https blog csdn net chinesekobe article details 111086664
  • 堆栈01--用两个栈实现队列

    堆栈01 用两个栈实现队列 jz05 题目概述 解析 参考答案 注意事项 说明 题目概述 算法说明 用两个栈来实现一个队列 完成队列的Push和Pop操作 队列中的元素为int类型 测试用例 队列先进先出 输入 1 2 输出 1 2 解析
  • 人工智能概念

    人工智能概念 人工智能就是用人工方法在机器 计算机 上实现的智能 或称机器智能 即是研究如何用计算机来表示和执行人类的智能活动 以模拟人脑所从事的推理 学习 思考和规划等思维活动 并解决需要人类的智力才能处理的复杂问题 如医疗诊断 管理决策
  • 算法学习——贪心算法之币种统计

    算法描述 币种统计 单位给每一位员工发工资 精确到元 为了保证不临时换零钱 使得每个员工取款的张数最少 在取工资前统计所有员工所需要的各种票面的张数 约定票种为100 50 20 10 5 2 1元 并验证币种统计是否正确 算法思路 算法描
  • Linux下进程退出的几种形式

    进程退出 Linux 下进程的退出分为正常退出和异常退出两种 1 正常退出 a 在main 函数中执行return b 调用exit 函数 c 调用 exit 函数 2 异常退出 a 调用about函数 b 进程收到某个信号 而该信号使程序
  • 【试题】排列组合

    在写一个远程的代码 如果本地有M个显示器 远程有N个显示器 M lt N 依据分辨率 显示器刷新频率等要求 需要对远程的N个显示器进行最佳分辨率修改 之后 需要从N个远程显示器中选择M个 跟本地显示器进行一对一的匹配 即从 A N M N
  • 查找数组中第二大的数

    快速找出一个数组中的最大数 第二大数 思路 如果当 前元素大于最大数 max 则让第二大数等于原来的最大数 max 再把当前元素的值赋给 max 如果当前的元素大于等于第二大数secondMax的值而小于最大数max的值 则要把当前元素的值
  • 索引优化之Explain 及慢查询日志

    索引 本质是数据结构 简单理解为 排好序的快速查找数据结构 以索引文件的形式存储在磁盘中 目的 提高数据查询的效率 优化查询性能 就像书的目录一样 优势 提高检索效率 降低IO成本 排好序的表 降低CPU的消耗劣势 索引实际也是一张表 该表
  • 基数排序代码实现

    详情请看排序总结 传送门 https blog csdn net m0 52711790 article details 121914543 基数排序的知识点我就不贴出来 相信都能搜到对应概念解释 下面就直接上代码 代码解释其实也很清晰了
  • 【数据结构】双链表的定义和操作

    目录 1 双链表的定义 2 双链表的创建和初始化 3 双链表的插入节点操作 4 双链表的删除节点操作 5 双链表的查找节点操作 6 双链表的更新节点操作 7 完整代码 嗨 我是 Filotimo 很高兴与大家相识 希望我的博客能对你有所帮助

随机推荐

  • Vue3:Typescript与组合式API、defineProps、defineEmits等使用

    标注类型 props 使用 defineProps 使用
  • 【SQL Server 2016】&【SSMS 17】安装

    一 SQL Server 2016安装 1 1 光盘映像下载 SQL Server Downloads 1 2 安装光盘映像 首次安装点击 全新SQL Server独立安装或向现有安装添加功能 产品密钥自动输入 下一步 勾选 我接受许可条款
  • 解决yolov7bug(Command ‘git tag‘ returned non-zero exit status 128.)(IndexError: list index out of ran)

    1 问题 执行train py Command git tag returned non zero exit status 128 原因 使用预训练权重 但路径错误 未找到本地预训练权重 它会自动下载 下载被墙 解决方法 从github下载
  • 透视投影详解

    透视投影详解 概述 投影变换完成的是如何将三维模型显示到二维视口上 这是一个三维到二维的过程 你可以将投影变换看作是调整照相机的焦距 它模拟了为照相机选择镜头的过程 投影变换是所有变换中最复杂的一个 视锥体 视锥体是一个三维体 他的位置和摄
  • electron 获取电脑mac地址遇到的坑

    最近公司需求做一个exe程序 无奈只是一个小前端 只能使用electron来实现了 其中一个需求就是每个账号绑定唯一的电脑 这里选用网卡的mac地址来做这个唯一的字段 代码很简单 测试也很顺利 const mainWindow new Br
  • 房地产投资占GDP比例畸高 中国房地产泡沫是一颗毒瘤

    转 http house ifeng com detail 2014 05 04 46139202 0 shtml 房地产投资占GDP比例畸高 2013年房地产投资占GDP比例高达16 而事实上从1960年来但凡房地产投资占GDP比例高于6
  • 昇思MindSpore安装教程

    目录 昇思MindSpore安装教程 MindSpore 安装MindSpore 开始安装 创建虚拟环境 进入工作目录 下载完成 验证是否成功安装 关注MindSpore社区官方号 昇思MindSpore安装教程 MindSpore 它是华
  • [js] : js 设置 style 的 important

    const div document getElementById xxx div style setProperty height 100px important api 详情 参见 CSSStyleDeclaration getProp
  • 论文笔记:Blockchain in Industries: A Survey

    一 基本信息 论文题目 Blockchain in Industries A Survey 发表时间 IEEE Access 2019 作者及单位 二 摘要 区块链技术近来已成为研究和工业界的最前沿 因为它们为许多行业带来了潜在的好处 这是
  • 02_Numpy学习笔记(下):随机采样

    02 Numpy学习笔记 下 随机采样 文章目录 02 Numpy学习笔记 下 随机采样 一 离散型随机变量的分布 1 二项分布 2 泊松分布 3 超几何分布 二 连续型随机变量的分布 1 均匀分布 2 正态分布 3 指数分布 三 其他随机
  • 华为OD机试真题 Java 实现【日志采集系统】【2023Q1 100分】,附详细解题思路

    目录 一 题目描述 二 输入描述 三 输出描述 四 解题思路 五 Java算法源码 六 效果展示 1 输入 2 输出 3 说明 一 题目描述 日志采集是运维系统的的核心组件 日志是按行生成 每行记做一条 由采集系统分批上报 如果上报太频繁
  • Python装饰器探究

    说在前边 装饰器作为Python中的一个比较实用的东西 在我们日常库的使用过程中经常使用 但是其细节问题我们却常常忘记考虑 本文章就此问题写建装饰器代码来进行一步一步分析 装饰器实验 1 我们常见的装饰器使用方式 from functool
  • ROS激光SLAM导航理解

    ROS激光SLAM导航理解 注 最近学习ROS的激光导航知识 需要理清ROS的SLAM 环境感知 costmap 与导航算法 为防止自己忘记 将觉得有价值的内容收集于此 对AGV来说 SLAM是个大大坑 环境感知和局部运动控制也是大坑 学习
  • 数据库添加/删除/修改 表字段(超详细)

    Oracle 添加 删除 修改 表字段 超详细 1 添加表字段 1 1 语法结构 1 2 举例说明 1 新建学生信息表 该步骤可忽略 2 初始表样子 3 语法解释 2 修改表字段 2 1 语法结构 1 修改字段属性 2 修改字段名 2 2
  • games101课程作业,在Vs2019环境下的配置环境(不使用虚拟机)

    为什么不使用虚拟机 因为虚拟机使用ubuntu x64版本系统 是一个从未接触过的系统 不好使用 虚拟机中无法使用中文输入法 无法对代码进行注释 不利于学习 虚拟机性能差 打开两三个文件就卡 令人抓狂 要使用终端进行编译 很是麻烦 还是喜欢
  • 面试经典-不被忽略的@property

    我们都知道 property是用来声明属性的 可以保存类的状态或信息 而与其相关的内容 诸如copy weak 深拷贝等 经常会在面试的过程中出现 接下来深入下这些模糊 熟悉的内容 理理顺 内容概要 1 property的本质 2 自动合成
  • Profinet 的交互流程

    Profinet 的交互流程 启动过程 在启动Profinet IO设备时 在设置IP地址之前 使用DCP协议 该协议类似于DHCP协议 PLC发送DCP广播消息 Identify 子网上的所有IO设备都使用本身的MAC地址进行应答 PLC
  • 机器学习算法与Python实践之(六)二分k均值聚类

    机器学习算法与Python实践之 六 二分k均值聚类 zouxy09 qq com http blog csdn net zouxy09 机器学习算法与Python实践这个系列主要是参考 机器学习实战 这本书 因为自己想学习Python 然
  • 基于IDEA的Java学生管理系统

    1 创建学生类 package studentManager public class Student 定义成员变量 private String num 学号 private String name 姓名 private String a
  • 善用Linux内核中的各种数据结构和算法

    1 介绍 在数据结构和算法一文中经常就信手拈来一些基本数据结构和算法 如链表 队列 栈 二叉树等等 但是在C的标准库中并没有自带这些 C 通过STL 类程序库等等会带这些 那么在嵌入式开发里面怎么快速方便使用这些数据结构和算法咧 答案就是从