深入浅出DPDK之内存特点和IOVA-程序员宅基地

技术标签: c++  DPDK  IOVA  Linux  linux  内存  

大页

DPDK通常是使用大页(hugepage)内存的,无论是2M的大页还是1G的大页,本质上都是为了减少TLB miss,通过更大的page size来提升TLB的命中率,而TLB就是用来缓存页表的高速缓存。

DMA

我们知道计算机的设备,如网卡硬件是不能处理用户空间的虚拟地址(只有CPU通过页表转换MMU才能识别虚拟地址),因为它不能感知任何用户态的进程和其所分配到的用户空间虚拟地址。相反,它只能访问真实的物理地址上的内存。

出于对效率的考量,现代硬件几乎总是使用直接内存存取(DMA)事务。通常,为了执行一个DMA事务,内核需要参与创建一个支持DMA的存储区域,将进程内虚拟地址转换成硬件能够理解的真实物理地址,并启动DMA事务。这是大多数现代操作系统中输入输出的工作方式;然而,这是一个耗时的过程,需要上下文切换、转换和查找操作,这不利于高性能输入/输出。

DPDK的内存管理以一种简单的方式解决了这个问题。每当一个内存区域可供DPDK使用时,DPDK就通过询问内核来计算它的物理地址,即DPDK维护了虚拟地址和物理地址的一个映射关系,由于DPDK使用锁定(如vfio_pin_map_dma)内存(防止物理内存和虚拟内存的映射关系变化),来使底层内存区域的物理地址不会改变,因此硬件可以依赖这些物理地址始终有效,即使内存本身有一段时间没有使用。然后,DPDK会在准备由硬件完成的输入/输出事务时使用这些物理地址,并以允许硬件自己启动DMA事务的方式配置硬件。这使DPDK避免不必要的开销,并且完全从用户空间执行输入/输出。

IOMMU和IOVA

默认情况下,任何硬件都可以访问整个系统的物理内存,因此它可以在任何地方执行DMA 事务。这有许多安全隐患。例如,流氓和/或不可信进程(包括在VM (虚拟机)内运行的进程)可能使用硬件设备来读写内核空间,和几乎其他任何存储位置。为了解决这个问题,现代系统配备了输入输出内存管理单元(IOMMU)。这是一种硬件设备,提供DMA地址转换和设备隔离功能,因此只允许特定设备执行进出特定内存区域(由IOMMU指定)的DMA 事务,而不能访问指定访问之外的系统内存地址空间。

由于IOMMU的参与,硬件使用的物理地址可能不是真实的物理地址,而是IOMMU分配给硬件的(完全任意的)输入输出虚拟地址(IOVA)。一般来说,DPDK社区可以互换使用物理地址和IOVA这两个术语,但是根据上下文,这两者之间的区别可能很重要。例如,DPDK 17.11和更新的DPDK长期支持(LTS)版本在某些情况下可能根本不使用实际的物理地址,而是使用用户空间虚拟地址来实现DMA。IOMMU负责地址转换,因此硬件永远不会注意到两者之间的差异。 在这里插入图片描述
如上图所示,P1和P2进程分别用虚拟地址P进行DMA,由于IOMMU将虚拟地址P映射到不同的物理地址,所以这并不会冲突,而P3访问的地址P并没有在IOMMU中建立映射关系,所以DMA访问会导致失败。

IO虚拟地址(IOVA)模式

DPDK是一个用户态应用框架,使用DPDK的软件可以像其他软件一样使用常规虚拟地址。但除此之外,DPDK还提供了用户态PMD和一组API,以实现完全以用户态执行IO操作。前文也已经提到过,硬件不能识别用户空间虚拟地址;它使用的是IO地址——物理地址(PA)或IO虚拟地址(IOVA)。

DPDK API对物理和IO虚拟地址不作区分,即使不是由IO内存管理单元(IOMMU)提供VA部分,也都以IOVA来代表两种地址。但DPDK却会区分物理地址作为IOVA的情况,和用户空间虚拟地址作为IOVA的情况。它们在DPDK API中被称为IOVA模式,可分为两种:PA作为IOVA模式,和VA作为IOVA模式。

PA作为IOVA模式

PA作为IOVA的模式下,分配到整个DPDK存储区的IOVA地址都是实际的物理地址,而虚拟内存的分配与物理内存的分配相匹配。该模式的一大优点就是它很简单:它适用于所有硬件(也就是说,不需要IOMMU),并且它适用于内核空间(将真实物理地址转换为内核空间地址的开销是微不足道的)。实际上,这就是DPDK长期以来的运作方式,在很多方面它都被认为是默认的选项。

然而,作为PA的IOVA模式也存在一些缺点。其中一个就是它需要根用户特权——如果无法访问系统的页面映射(因为DPDK要维护虚拟地址和物理地址IOVA的对应关系),DPDK就无法获取内存区域的真实物理地址。因此,如果系统中没有root权限,就无法以该模式运行。 在这里插入图片描述
PA作为IOVA的模式还有另外一个值得一提的限制——虚拟内存分配要遵循物理内存分配。这意味着如果物理内存空间被分段(被分成许多小段而不是几个大段)时,虚拟内存空间也要遵循同样的分段。极端情况下,分段可能过于严重,导致被分割出来物理上连续的片段数量过多,耗尽DPDK用于存储这些片段相关信息的内部数据结构,就会让DPDK初始化失败。在这里插入图片描述
应对这些问题,DPDK社区提出了解决方法。举例来说,一种减少分段影响的方式是使用更大的分页——问题虽然没被解决,但是单独的1千兆字节(GB)段比独立的2兆字节(MB)段能大幅度减小分段的数量。另外一种广泛使用的解决方式则是在启动时引导系统并保留大页,而不是在运行时。但上述的解决方法都不能根本地解决问题,而且整个DPDK社区都习惯了要去解决这些问题,每个DPDK用户(有意或无意)在使用时都会采取相同的思维模式——“我需要X MB内存,但以防万一,我要保留X + Y MB!”

【文章福利】小编推荐自己的Linux、C/C++技术交流群:【960994558】整理了一些个人觉得比较好的学习书籍、大厂面试题、有趣的项目和热门技术教学视频资料共享在里面(包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等等.),有需要的可以自行添加哦!~
在这里插入图片描述

VA作为IOVA模式

相比之下,VA作为IOVA的模式不需遵循底层物理内存的分布。而是重新分配物理内存,与虚拟内存的分配匹配。DPDK EAL依靠内核基础设施来实现这一点。内核基础设施又反过来使用IOMMU重新映射物理内存。 在这里插入图片描述
这种方式的优点显而易见:VA作为IOVA的模式下,所有内存都是VA和IOVA连续的。这意味着所有需要大量IOVA连续内存的内存分配更有可能成功,因为对硬件来说,即使底层物理内存可能不存在,内存看上去还是IOVA连续的。由于重新映射,IOVA空间片段化的问题就变得无关紧要。不管物理内存被分段得多么严重,它总能被重新映射为IOVA-连续的大块内存。 在这里插入图片描述
VA作为IOVA的模式还有另一个优点,它不需要任何权限。这是因为它不需要访问系统页面映射。这样就可以允许以非root用户身份运行DPDK,而且在特权访问不受欢迎的环境中,如云原生环境就可以更加容易地使用DPDK。

当然, 作为VA的IOVA模式也有一个缺点。出于各种原因,有时候可能不能选择使用IOMMU。这种情况可能包括:

  1. 硬件不支持IOMMU;

  2. 平台可能本身就没有IOMMU(比如没有IOMMU模拟的VM);

  3. 软件设备(例如,DPDK的内核网络接口(KNI)PMD)不支持作为VA的IOVA模式;

  4. 一些IOMMU(通常是模拟的IOMMU)的地址宽度可能有限,虽然这不妨碍用作VA的IOVA模式,但限制了其有效性;

  5. 在非Linux *的操作系统上使用DPDK;

但是,这些情况还是相对较少,绝大多数情况下,VA作为IOVA的模式都可以正常工作。

IOVA模式的选择

很多情况下,DPDK默认选择作为PA的IOVA模式,因为从硬件角度这是最安全的模式。所有给定的硬件(或软件)PMD至少都可以保证支持作为PA的IOVA模式。尽管如此,如果条件允许,还是强烈建议所有DPDK用户使用作为VA的IOVA模式,毕竟此模式具有不可否认的优势。

但是,用户不必非要在两者中选择一个。可以自动检测出最合适的IOVA模式,而且默认选项绝对适用于大多数情况,因此不需要用户来做此选择。如果默认选项并不合适,用户可以使用–iova-mode EAL命令行参数尝试使用EAL标志(适用于DPDK 17.11及更高版本)来代替IOVA模式:

1 ./app --iova-mode=pa # use IOVA as PA mode

2./app --iova-mode=va # use IOVA as VA mode

大多数情况下,VA和PA模式不会互相排斥,可以使用任一模式,但在某些情况下,PA作为IOVA的模式是唯一可用的选择。当不能使用作为VA模式的IOVA时,即使EAL参数要求使用作为VA模式的IOVA,DPDK也会自动切换为作为PA模式的IOVA。DPDK还提供了一个API,可查询运行时正在使用的IOVA模式,但通常这不会在用户应用中使用,因为只有像是DPDK PMD和总线驱动程序才会要求获取这种信息。

UIO和VFIO对IOVA的支持

l Igb_uio

DPDK代码库中最早的内核驱动程序是igb_uio驱动程序。在DPDK最初的发展阶段,这个驱动程序就已经存在了,因此它是DPDK开发人员使用最广泛也是最熟悉的驱动程序。

此驱动程序依赖内核用户空间IO(UIO)基础结构运作,并为所有中断类型(INT、消息信号中断(MSI)和MSI-X)提供支持,以及创建虚拟功能。它还公开硬件设备通过/dev/uio文件系统注册和中断句柄,然后DPDK EAL将它们用于将它们映射到用户空间并使它们可用于DPDK PMD。

gb_uio驱动程序非常简单,能做的也并不多,因此它不支持使用IOMMU。或者,更确切地说,它确实支持IOMMU,但仅在传输模式下,它在IOVA和物理内存地址之间建立1:1映射。igb_uio不支持使用完整的IOMMU模式。因此,igb_uio驱动程序仅支持PA作为IOVA模式,并且根本无法在IOVA中作为VA模式工作。

类似于igb_uio的驱动程序在内核中可用:uio_pci_generic。它的工作方式与igb_uio非常相似,只是它的功能更加有限。例如,igb_uio支持所有中断类型(传统,MSI和MSI -X),而uio_pci_generic只支持传统中断。更重要的是,igb_uio可以创建虚拟函数(Virtual Function, VF),而uio_pci_generic则不能;因此,如果在使用DPDK物理函数(Physical Function, PF)驱动程序时创建VF是必需的一步,igb_uio是唯一的选择。

因此,在大多数情况下,igb_uio与uio_pci_generic相同或更可取。关于使用IOMMU的所有限制同样适用于igb_uio和uio_pci_generic驱动程序 - 它们不能使用完整的IOMMU功能,因此仅支持IOVA作为PA模式。

l vfio

vfio-pci驱动是虚拟功能I / O(VFIO)内核基础结构的一部分,并在Linux 3.6版中引入。VFIO使设备寄存器和设备中断可供用户空间应用程序使用,并可使用IOMMU设置IOVA映射以从用户空间执行IO。后一部分至关重要,此驱动程序专为与IOMMU一起使用而开发,在较旧的内核上,如果没有启用IOMMU,它甚至都无法工作。

与直观看法相反,使用VFIO驱动程序允许使用PA作为IOVA和VA作为IOVA模式。这是因为,虽然建议使用IOVA作为VA模式来利用该模式的所有好处,但没有什么能阻止DPDK的设置IOMMU映射的EAL以遵循物理内存布局1:1的方式;毕竟IOVA映射是任意的。在这种情况下,即使使用IOMMU,DPDK也可以在IOVA中作为PA模式工作,从而允许DPDK KNI等工作。但是,仍然需要root权限才能将IOVA用作PA模式。

在更新的内核(4.5+,向后移植到一些旧版本)上,有一enable_unsafe_noiommu_mode选项,允许在没有IOMMU的情况下使用VFIO。这种模式适用于与基于UIO的驱动程序相同的所有意图和目的,并具有所有相同的优点与限制。

17.11及早期版本

使用DPDK库17.11版本或更早版本的任何应用程序必须事先知道其内存要求。这是因为,对于这些版本的DPDK,在初始化之后不可能再申请额外的大页内存,或者将其释放回系统。因此,DPDK应用程序可能使用的任何内存都必须在应用程序初始化时预留,并在应用程序的整个生命周期都由DPDK保留。

在决定要保留的内存量时,留出一些余量通常是个好主意。在各种内部分配中,某些DPDK内存将在不同的内部分配中被“浪费”,数量会因您的配置而异(DPDK将使用的设备数量,启用功能等)。

此外,DPDK17.11中的大多数API都需要大量的IOVA连续内存。这是因为在DPDK 17.11中,虚拟内存布局总是与物理内存布局相匹配。换句话说,如果使用PA作为IOVA,则要求PA是连续的。这是DPDK17.11内存管理中众所周知的问题之一:实际上很少有应用程序需要PA连续内存,由于缺少足够的IOVA连续内存,分配大量内存可能会失败。在这里插入图片描述
上述限制当然仅适用于作为物理地址(PA)模式的IOVA,因为在该模式下,DPDK的虚拟地址(VA)空间遵循PA空间的布局。在PA模式的IOVA中,可用IOVA连续内存量取决于DPDK控制之外的许多因素,尽管DPDK将尝试保留尽可能多的IOVA连续内存,具体取决于可用内存量和系统配置,可能没有足够的IOVA连续内存来满足所有分配。

在VA模式的IOVA中,这不是问题,因为在这种情况下,IOVA空间布局将与VA空间的布局相匹配(而不是相反),并且所有物理内存都被重新映射为IOVA连续到硬件。

18.11及之后版本

动态内存管理

DPDK 18.11的最大变化是可以在运行时增加和减少内存使用量,从而消除了DPDK内存映射为静态的情况,这带来了许多可用性方面的改进。

在DPDK 17.11中,运行没有任何环境抽象层(EAL)参数的DPDK应用会保留所有可用的大页内存供其使用,且不会为其他应用程序或其他DPDK实例留下任何大页内存。对于DPDK18.11而言情况有所不同,DPDK仅保留应用运行所必须的内存量。在这种意义上,DPDK现在性能更好,并且使DPDK与其他应用程序完美配合所需的工作也更少。

同样,不再需要事先知道应用程序的内存需求,DPDK的内存映射可以动态增加和减少,因此DPDK内存子系统可以根据需要自动增加其内存使用量,并在不再需要时将内存返回给系统。这意味着部署DPDK应用程序所需的工作更少,因为现在DPDK可以自行管理其内存需求。

DPDK 18.11和IOVA连续性

DPDK 18.11中的一项基本后台更改是,不能保证虚拟地址(VA)连续内存是IOVA连续的;两者之间不再有任何关联。在VA作为IOVA的模式下,IOVA布局仍然像以前一样遵循VA布局,但是在PA作为IOVA的模式下,PA布局是任意的(物理页面要向后映射并不罕见)。在这里插入图片描述
这种改变并不像看起来那样具有颠覆性,因为实际上没有多少数据结构需要IOVA连续内存。所有软件数据结构(环,内存池,哈希表等)仅需要VA连续内存,而不在意底层物理内存布局。这使得在早期DPDK版本上工作的大多数用户应用程序可以无缝过渡到新版本,而无需更改代码。

尽管如此,某些数据结构确实需要IOVA连续内存(例如,硬件队列结构),对于这些情况,引入了新的分配器标志。使用此标志,可以使memzone分配器尝试分配IOVA连续的内存。

单个文件段

较旧的DPDK版本在hugetlbfs文件系统中的每个大页上存储一个文件,这适用于大多数用例,但有时会出现问题,特别是,vhost-user后端的Virtio将与后端共享文件,并且有可共享文件描述符数量的硬性限制。当使用大页(例如1 GB的页面)时,它可以很好地工作,但是在页面大小较小的情况下,文件数量会很快超过文件描述符限制。

为了解决此问题,版本18.11中引入了一种新模式,即单文件段模式,该模式通过–single-file-segments EAL命令行标志启用,这使得EAL在hugetlbfs中创建的文件更少,并且使具有vhost-user后端的Virtio甚至可以在最小页面大小下工作。

以上有不足的地方欢迎指出讨论,觉得不错的朋友希望能得到您的转发支持,同时可以持续关注我,每天分享Linux C/C++后台开发干货内容!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_52622200/article/details/112611498

智能推荐

matlab写一段 计算期权DELTA和GAMMA值并绘图的代码-程序员宅基地

文章浏览阅读442次。下面是一段简单的 Matlab 代码,可以计算期权的 delta 和 gamma 值并绘图:% 定义期权参数S = 50; % 标的资产价格K = 55; % 行权价格r = 0.05; % 无风险利率T = 1; % 期权到期时间sigma = 0.3; % 标的资产波动率% 计算 delta 和 gamma 值d1 = (log(S/K) + (r + sigma^2/2)*..._matlab 计算期权gamma

matlab 避障代码,基于模糊控制的MATLAB避障算法-程序员宅基地

文章浏览阅读1.2k次。基于模糊控制的MATLAB避障算法matlab2021-1-18下载地址https://www.codedown123.com/59892.html基于模糊控制的MATLAB避障算法,课设内容,最后效果还不错。资源下载此资源下载价格为2D币,请先登录资源文件列表fangzhen/fuzzy/CheckIsBlocked.asv,709fangzhen/fuzzy/CheckIsBlocked...._模糊控制机器人避障代码

大数据框架基础Hadoop MapReduce简介_maprduce是hadoop中的大数据计算框架,下例哪一项是高度抽象函数‘-程序员宅基地

文章浏览阅读429次。然后介绍典型的批处理模式 MapReduce,最后对 Map 函数和 Reduce 函数进行描述。批处理模式批处理模式是一种最早进行大规模数据处理的模式。批处理主要操作大规模静态数据集,并在整体数据处理完毕后返回结果。批处理非常适合需要访问整个数据集合才能完成的计算工作。例如,在计算总数和平均数时,必须将数据集作为一个整体加以处理,而不能将其视作多条记录的集合。这些操作要求在计算..._maprduce是hadoop中的大数据计算框架,下例哪一项是高度抽象函数‘

二维图像傅里叶变换可视化的例子-程序员宅基地

文章浏览阅读975次。在网上很粗略地搜了一下,没发现比较好的例子。先自己用matlab做了一些供参考。matlab对应的代码:% clc;clear;c1 = imread('../images/symmetric1.jpg');c2 = imread('../images/symmetric2.png');c3 = imread('../images/exp_fft2.jpeg');F..._图片傅里叶 可视化

杂谈数据中心靠什么活在一线城市?_一线城市土地资源有限的情况下,你们以为拿下自建大型idc中心-程序员宅基地

文章浏览阅读409次。中国的IDC市场,萌芽状态要追溯到2010年以前,但是从2012年开始,就提早进入了蛮荒时代。当时国内的三大电信运营商出于电力和土地资源的考虑,相继将战线转移到中小城市。但是似乎在客户的问题上没有太多考虑,导致后来很少有客户愿意为这些远在漠北苦寒之地的IDC买单。不过也有一些聪明的厂商为包头,呼和浩特等地方政府发展政务云建设数据中心,如此倒是赚了个名利双收。建设数据中心花在水电费和地租上的钱,..._一线城市土地资源有限的情况下,你们以为拿下自建大型idc中心

MicroPython-TPYBoard固件编译教程_micropython固件结构-程序员宅基地

文章浏览阅读773次。本文主要介绍一下,在Linux环境下编译micropython固件的方法和流程。  首先,我们先来看一下MicroPython的源码结构。  github地址:https://github.com/micropython/micropython  你会发现,micropython根据不同的MCU运行平台进行了分类,比如esp8266目录下就是esp8266-WIFI模块上的mic..._micropython固件结构

随便推点

C++11 标准新特性:Defaulted 和 Deleted 函数-程序员宅基地

文章浏览阅读46次。本文参考:http://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/#ibm-pconC++11 标准的两个新特性:defaulted 和 deleted 函数。对于 defaulted 函数,编译器会为其自动生成默认的函数定义体,从而获得更高的代码执行效率,也可免除程序员手动定义该函数的工作量。对于 deleted...

Python修改元组的元素值_python将元组(1,2,3,4)中第二个元素修改为5-程序员宅基地

文章浏览阅读4.3k次,点赞2次,收藏5次。输入矩形块儿维度dimensions = (200, 50)print(dimensions[0])print(dimensions[1])输出20050修改元组索引位置0出的值dimensions[0] = 1print(dimensions[0])####元组元素无法修改打印结果Traceback (most recent call last): File "D..._python将元组(1,2,3,4)中第二个元素修改为5

Fabric安装与部署(fabric v2.0.0 版本)_fabric部署-程序员宅基地

文章浏览阅读1.4w次,点赞10次,收藏35次。目录一、使用Docker快速运行Fabric网络1、环境配置1.1、操作系统安装1.2、安装go语言环境1.3、安装依赖包2、安装Docker服务3、安装docker-compose二、启动Fabric网络1、准备工作2、开始运行test-network测试网络3、运行first-network(end-to-end测试)三、总结:一、使用Docker快速运行Fabric网络1、环境配置......_fabric部署

php ftp 创建文件夹失败,php ftp_put失败怎么办-程序员宅基地

文章浏览阅读449次。php ftp_put失败的解决办法:首先打开“Upload/Driver/Ftp.class.php”;然后使用“ftp_pasv($this->link,true);”方法切换到被动模式;最后在客户端重新上传文件即可。推荐:《PHP教程》PHP Upload FTP驱动 ftp_put 函数上传失败问题2台服务器,一台做ftp服务器,一台做web服务器。我使用的thinkphp3.2得U..._ftp 不能put

以下不是合法c语言转义字符的是,以下C语言转义字符表示不正确的是____。-程序员宅基地

文章浏览阅读585次。摘要:下C语言转义字通常将具有 mRNA 功能的链称为正链。酶催化反应是发生在酶的活性部位,正确酶之所以具有高效率是由于活性部位存在多种催化基团,正确起着多元催化的作用,其它部分只是维持酶的催化基团具有合适的位置,对催化作用不起什么作用。在酶的活性中心,下C语言转义字只有侧链带电荷的氨基酸残基直接参与酶的催化作用。...下C语言转义字通常将具有 mRNA 功能的链称为正链。符表以下正确的观点是?酶..._不是合法c语言转义字符

XML特殊字符转义_正则表达式转义xml特殊字符-程序员宅基地

文章浏览阅读705次。XML 特殊字符 转义下面是五个在XML文档中预定义好的实体:< > > 大于号 & & 和 &apos; ' 单引号 " " 双引号 实体必须以符号"&"开头,以符号";"结尾。 注意: 只有"_正则表达式转义xml特殊字符