如何使虚拟地址在物理地址区域中连续进行以提高性能?

时间:2019-04-23 05:24:28

标签: c linux linux-kernel dpdk huge-pages

最近,我正在dpdk(dpdk.org)中阅读有关大页面的代码。我看到代码故意使虚拟地址在物理地址区域中连续。具体来说,它首先检查大页面中是否存在物理连续区域,然后将物理连续区域映射到连续虚拟地址。这如何提高性能?

source code说:

  

要保留大量连续的内存,我们使用linux的巨大页面功能。为此,我们需要安装ugeltlbfs。此代码将在此目录中创建许多文件(每页一个),并将它们映射到虚拟内存中。对于每个页面,我们将检索其物理地址并对其进行重新映射,以拥有虚拟的连续区域和物理的连续区域。

为什么需要重新映射?

1 个答案:

答案 0 :(得分:1)

  

将物理上连续的区域映射到连续的虚拟地址。这如何提高性能?

DPDK同时需要物理和虚拟地址。虚拟地址通常用于加载/存储一些数据。物理地址是用户空间驱动程序与设备之间进行数据传输所必需的。

例如,我们分配了几个mbuf,它们的虚拟地址为0x410000x420000x43000。然后,我们用一些数据填充它们,并将这些虚拟地址传递给PMD进行传输。

驱动程序必须将这些虚拟地址转换为物理地址。如果物理页面不连续地映射到虚拟地址空间,则要将虚拟地址转换为物理地址,我们需要搜索所有映射。例如,虚拟地址0x41000可能对应于物理地址0x810000x42000对应于0x16000,而0x43000 —对应于0x64000

这种搜索的最佳情况是读取一个内存,最坏的情况是每个缓冲区读取几个内存

但是,如果我们确定存储区的虚拟地址和物理地址都是连续的,则只需在虚拟地址上添加一个偏移量即可获得物理地址,反之亦然。例如,虚拟0x41000对应于0x81000,虚拟0x42000对应于物理0x82000,以及0x430000x83000

我们从映射中知道的偏移量。这种转换的最坏情况是突发中每个缓冲区读取一个内存,这对于转换是一个巨大的改进。

  

为什么需要重新映射?

要将大型页面映射到虚拟地址空间,请使用mmap系统调用。调用的API允许为要映射的大页面指定固定的虚拟地址。这样一来,就可以映射大页面,从而创建一个连续的虚拟内存区域。例如,我们可以在虚拟地址mmap0x200000放置一个大页面,在虚拟地址0x400000处下一个页面,依此类推。

不幸的是,在映射大页面之前,我们不知道它们的物理地址。因此,我们可以在虚拟地址0x200000上映射物理地址0x800000,并在虚拟地址0x400000上映射物理0x600000

但是,当我们第一次映射那些大页面时,我们既知道物理地址又知道虚拟地址。因此,我们要做的就是以正确的顺序重新映射它们::在虚拟地址0x1200000上,我们映射了物理0x600000,而在0x1400000上则映射了物理{{ 1}}。

现在,我们有一个虚拟和物理上连续的存储区,从虚拟地址0x800000和物理地址0x1200000开始。因此,要将虚拟地址转换为该存储区中的物理地址,我们只需如上所述从虚拟地址中减去偏移量0x600000

希望这可以澄清连续内存区域和重新映射的概念。