2

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

源代码说:

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

为什么需要重新映射?

4

1 回答 1

1

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

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

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

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

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

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

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

为什么需要重新映射?

要将大页面映射到虚拟地址空间,需要mmap使用系统调用。调用的 API 允许为要映射的大页面指定固定的虚拟地址。这允许一个接一个地映射大页面,创建一个连续的虚拟内存区域。例如,我们可以mmap在虚拟地址处创建一个大页面,在虚拟地址处创建0x200000下一个页面0x400000,以此类推。

不幸的是,我们不知道大页面的物理地址,直到它们被映射。所以在虚拟地址0x200000我们可以映射物理地址0x800000,在虚拟地址0x400000——物理地址0x600000

但是一旦我们第一次映射这些大页面,我们就知道物理地址和虚拟地址。所以我们需要做的就是以正确的顺序重新映射它们:在虚拟地址0x1200000我们映射物理地址0x600000,在0x1400000物理地址0x800000

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

希望这能澄清一下连续内存区域和重新映射的想法。

于 2019-04-24T23:06:19.677 回答