DPDK Ring

news2024/10/5 18:25:14

无锁环ring是DPDK提供的一种较为基础的数据结构,其支持多生产者和多消费者同时访问。
经过我的经验,无锁结构的实现主要依靠两方面:

  1. 最终的数据交换一定要是原子级的操作,最常用到的自然就是比较后交换(Compare And Swap,CAS)
  2. 数据的实际写入与原子级的交换操作相分离

只是这么说可能不是很好理解,我们以我目前知道的两种实现方式,即RCU和DPDK ring的实现来举例子就好理解了。

CAS

首先我们需要之后CAS的原理,CAS共有三个输入,分别是将要修改的地址reg,reg中的原数据oldvalue,以及想要更新的新数据newvalue。

在CAS的执行流程如下:

  1. 取出reg中的当前数据regvalue
  2. 将regvalue与oldvalue进行比较
  3. 如果二者相等说明在当前核读取数据到写入数据的这一段时间reg中的值没有被修改过,可以直接写入。CAS函数在写入后返回成功信号
  4. 如果二者不等说明该数据已经被修改过了,当前核使用的数据有可能是错的,因此不会执行写入操作,并返回一个错误信号

上述的所有步骤均由一个原子级的CPU指令完成,在CAS失败时,通常需要用户重新读取新数据执行对应操作,再尝试执行一次CAS,直到写入成功为止。

RCU和无锁Ring

RCU和无锁Ring都是无锁通信的实现,二者在原理上有上述的类似却又不同,适用场景也不同。
首先,既然是CPU之间的通信,那么就一定会有数据被修改,加锁也只是为了保证写核在修改数据时不会被其他读核读取到数据。
而CAS恰恰就是一个原子级的操作,也就是说通过CAS在修改数据的时候,别的核是无法读取到对应数据的,也就是相当于自带加锁了。
那既然有了CAS为什么不能所有数据都这样写呢?因为种种原因(例如CPU指令集限制,以及需要比较的字节数等等),CAS只支持基本数据类型(int, bool)维度的操作。
那假如我要修改一个很长的结构体对象该怎么办呢?

RCU

原理

很自然的可以想到,我们可以先创建一个新的结构体对象,这个对象不会被任何其他核访问到,无论花多少时间都可以。
在对象创建好之后,我们取出他的指针,由于指针是基本数据类型,我们可以使用CAS完成一次狸猫换太子,将指向原来对象的指针替换成新对象的指针,这样之后的读核就会无感的访问到新对象了。
在完成指针更新之后,为了防止内存泄露,我们需要将原来的对象释放掉。
这里就需要注意一个问题,原来的数据结构可能还在被其他核所读取,冒然释放可能引发系统错误,因此我们要等所有读核都不在使用该地址再进行释放。
也就是说这块内存会额外存活一段时间,这段时间在RCU中就被成为宽限区,宽限区从写核修改指针开始,到所有读核读取结束为止。
为了让写核能够感知到释放内存的时间,需要为每一个对象内存添加一个引用计数。读核每次开始读取时引用计数加1,结束读取时引用计数减1,当引用计数为0就说明可以释放了。
至此我们已经掌握了RCU的基本原理。

特点

优点:对于读核来说无需进行任何加锁操作,只需要在开始读取和结束读取时修改一个引用计数,这一操作同样可以使用CAS实现。
缺点:拖慢写核的工作进程,同时需要额外的内存地址,无法做到原址修改。
因此RCU适合读多写少,并且不需要原址修改的场景中。

无锁Ring

原理

假如我们想要实现一个存储对象的循环队列,队列的底层是一个数组,自然需要在原址修改,此时RCU就不适用了,我们需要实现新的无锁方案。
为了利用CAS,我们需要找到能够代表一个对象的基本数据类型,那自然是对象在数组中的索引了。
在写入时,我们可以先修改队尾的下标地址,相当于在实际写入数据之前通告其他写核,这块地址已经被我占据了,你们不要再往里面写了,由于交换的只是一个索引,因此可以使用CAS。
在新下标确定之后,写核会对数据进行实际的写入,这里有一个问题,由于我们已经修改了队尾指针,那么虽然其他写核访问不到这片内存,但是现在其他读核可以了啊。
解决方法也很简单粗暴,我们再加一个索引就好了。新加的索引在没有写操作进行时指向与队尾相同的位置,在开始写入时不变,写入结束时再与队尾同步,只要让读核所看到的队尾一直是该索引即可。
当然,上述讨论的只是多生产者单消费者的情况,如果是多生产者多消费者,那么我们需要为队头也创建一个额外的索引,其余原理其实都相同。
至此,我们就掌握了无锁循环队列的基本原理。

DPDK实现

下图展示的是DPDK中无锁Ring的基本结构,其中prod_head和prod_tail分别上述的队尾指针和队尾额外指针,同样cons_head和cons_tail也是队头指针和队头额外指针。
对于生产者来说,它在任意时刻看到的队列实际是prod_head到cons_tail,而对消费者来说,其看到的队列始终是prod_tail和cons_head。

在这里插入图片描述

DPDK Ring单生产者入队流程

下面是单生产者的入队流程,我们已经介绍过了
需要注意的是,local variables中的prod_head核prod_next分别是CAS操作中的oldvalue和newvalue,而队列中的prod_head则是reg。
第一步:读取原始prod_head,根据入队数量计算新的prod_head,即prod_next
在这里插入图片描述

第二步:通过CAS修改prod_head,占据内存
在这里插入图片描述
第三步:实际写入数据,并使用CAS修改prod_tail
在这里插入图片描述

DPDK Ring多生产者入队流程

在这里插入图片描述
第二步:先提交的核完成CAS占据内存,后提交的CAS失败,重新读取prod_head并计算prod_next
在这里插入图片描述
第三步:core1开始写入数据,core2重新CAS成功
在这里插入图片描述
第四步:core2写入数据,core1通过CAS修改prod_tail
在这里插入图片描述
第五步:core2修改prod_tail,至此多生产者入队结束。
在这里插入图片描述
由于消费者出队的操作与生产者入队几乎完全相同,在此不做赘述,可以参考https://dpdk-docs.readthedocs.io/en/latest/prog_guide/ring_lib.html

优点:可以原址修改,支持批量入队和出队,也就是可以通过一次CAS占据大片内存,这都是RCU做不到的。如果使用CAS直接操作内存地址队列,也做不到批量操作。
缺点:内存空间需要预先分配,不像RCU使用是才申请,比较费内存。

进程间通信

通过Ring和mempool的结合使用还可以实现进程间的通信,原理与共享内存类似,DPDK在创建Primary Process时会将使用的大页内存的详细信息记录到文件中,在启动Secondary Process时会读取这些信息,这样就能实现类似共享内存的效果。
在两个进程内都需要调用rte_eal_init初始化DPDK环境。
在一个进程内创建Ring和Mempool,在另一个进程内调用rte_ring_lookup和rte_mempool_lookup函数获取对应的Ring和Mempool。
通信时,一个进程从Mempool中取一个元素,放入Ring中,另一个进程从Ring中取出,处理完之后再放回Mempool即可。

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

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

相关文章

Java项目:SSM个人博客网站管理系统

作者主页:源码空间站2022 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目包含管理员与游客两种角色; 管理员角色包含以下功能: 发表文章,查看文章,类别管理,添加类别,个人信息管理,评论…

DeepSort目标跟踪算法

DeepSort目标跟踪算法是在Sort算法基础上改进的。 首先介绍一下Sort算法 Sort算法的核心便是卡尔曼滤波与匈牙利匹配算法 卡尔曼滤波是一种通过运动特征来预测目标运动轨迹的算法 其核心为五个公式,包含两个过程: 其分为先验估计(预测&…

[附源码]计算机毕业设计人事管理系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

UE4中抛体物理模拟UProjectileMovementComponent

UE4中抛体物理模拟UProjectileMovementComponent1.简述2.使用方法3.绘制抛物曲线4.绘制抛物曲线1.简述 背景:实现抛体运动,反弹效果,抛物曲线等功能 通用实现可以使用spline绘制,物体按照下图接口可以根据时间更新位置 USplineC…

CN_MAC介质访问控制子层@CSMA协议

文章目录常用方法静态方法信道划分MAC特点动态方法随机访问MACCSMA协议CSMA/CD多点接入(或多点访问):载波监听Note:🎈碰撞检测碰撞:碰撞冲突过程传播时延对载波侦听的影响🎈争用期发现碰撞的最迟情况电磁波的速率是有限最短帧长🎈小结&#x…

CAD重复圆绘制机械图形

这次CAD必练图形第四个,这个图形主要用到了CAD圆、直线、修剪、旋转等多个命令,看着不简单,等绘制出来后就觉得还是挺简单的。 目标图形 操作步骤 1.使用CAD直线命令绘制一条水平的直线和四条垂直的直线,四条垂直的直线之间的距…

【网络层】DHCP协议(应用层)、ICMP、IPv6详解

注:最后有面试挑战,看看自己掌握了吗 文章目录DHCP------DHCP服务器来动态分配IP--------应用层协议----允许地址重用ICMP字段----差错报文、询问报文差错报文-----终点不可达无法交付--------源点抑制、拥塞丢数据(现在废弃)----…

JAVA小区物业管理系统(源代码+论文)

毕业设计(论文) [摘要] 物业管理系统是紧随当今时代发展的需要,目的在于实现不同的人员对物业系统的不同的需要,有利于社会的稳定和顺利发展。 关键词:小程序Applet;应用程序Application;数据库;数据库实现&#xf…

12.5 - 每日一题 - 408

每日一句:没有醒不来的早晨,弄不懂的题目,熬不过的迷茫,只有你不敢追的梦。 数据结构 1 在最后一趟排序开始之前,所有记录有可能都不在其最终位置上的是______。 A. 直接插入排序B. 冒泡排序C. 堆排序D. 快速排…

底层逻辑-理解Go语言的本质

1.Java VS Go语言 Java,从源代码到编译成可运行的代码 上图已经展示了这个过程:从Java的源代码编译成jar包或war包(字节码),最终运行在JVM中。 我们把Java源代码编译后的jar包或war包看成是工程师生产出来的产品,操作系统是一个平台,JVM就是…

【RCNN系列】RCNN论文总结

目标检测论文总结 【RCNN系列】 RCNN RCNN目标检测论文总结前言一、Pipeline二、模型设计1.warp2.SVM3.阈值设定4.box回归三、思考四、缺点前言 一些经典论文的总结。 一、Pipeline 首先传入Input image,利用Selective Search(比较古老)算法…

【计算机网络】数据链路层:拓展的以太网

在物理层拓展以太网: 使用光纤拓展:主机使用光纤和一对光纤调制解调器连接到集线器。 使用集线器拓展:使用集线器连成更大的以太网 集线器优点: 使原来不同碰撞域的计算机能够跨碰撞域通信,扩大了以太网覆盖的地理范…

GDB使用技巧和相关插件

GDB使用-小技巧 参考:《100个gdb小技巧》 链接中的文档有许多关于GDB的使用小技巧; $info functions - 列出函数的名称 $s/step - 步入,进入带有调试信息的函数 $n/next - 下一个要执行的程序代码 $call/print - 直接调用函数执行 $i/info …

jvm简介

.什么是JVM? JVM是Java Virtual Machine(Java虚拟机)的缩写,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。JVM屏蔽了与操作系统平台相…

Postman如何做接口测试,那些不得不知道的技巧

目录:导读 前言 Postman如何做接口测试1:如何导入 swagger 接口文档 Postman如何做接口测试2:如何切换测试环境 Postman如何做接口测试3:什么?postman 还可以做压力测试? Postman如何做接口测试4&…

电源控制测试老化系统-国产电源测试仪器-电源模块测试系统NSAT-8000

*测试仪器:可编程直流电源、可编程直流电子负载、数字示波器、功率计 *测试产品:电源模块。纳米软件电源ATE自动测试系统适用于大功率工业电源、AC/DC类DC电源供应器、适配器、充电器、LED电源等开关电源之综合性能测试。 *被测项目:有效值电…

快来组战队,赢iPhone啦!

常见问题 问:我邀请的人再去邀请,也算我的战队队员么?我最多可以有多少个队员? 答:您将和您直接邀请的人组成战队,并担任该战队的队长。如果被您邀请的小伙伴再去邀请其他人,那么您邀请的小伙…

跨域推荐(Cross-Domain Recommendation)的最新综述

论文解读系列第十六篇:IJCAI 2021--跨域推荐(Cross-Domain Recommendation)的最新综述 - 知乎 数据稀疏问题 目录 1.背景介绍 (1)内容层级相关性(content-level relevance) (2)用户层级相关性(user-level relevance) (3)产品层级相关性…

OpenCV从2到3的过渡

与版本2.4相比,OpenCV 3.0引入了许多新算法和功能。有些模块已被重写,有些已经重组。尽管2.4中的大多数算法仍然存在,但接口可能不同。本节描述了一般性的最显着变化,过渡操作的所有细节和示例都在本文档的下一部分中。 1、贡献存…

nginx安装与配置反向代理

Nginx (engine x) 是一款基于异步框架的轻量级/高性能的Web 服务器/反向代理服务器/缓存服务器/电子邮件(IMAP/POP3)代理服务器,由俄罗斯的程序设计师Igor Sysoev(伊戈尔赛索耶夫)所开发.话不多说直接上步骤 1.安装nginx,我是在root用户下不需要加sudo yum install nginx 安…