C 分配连续物理内存的方法

C 分配连续物理内存的方法,c,memory,C,Memory,我知道,使用C malloc和posix_memaligh可以从进程的虚拟地址空间分配连续内存。然而,我想知道人们是否能以某种方式分配一个物理上连续的内存缓冲区?我正在调查利用二级缓存的侧通道攻击,因此我希望确保能够访问正确的缓存线。在(几乎[注1])所有虚拟内存架构上,虚拟内存都以“页面”为单位映射到物理内存。页面的大小(几乎)总是2的幂,并且页面按该大小对齐,因为映射仅通过使用地址的高阶位完成。页面大小通常为4K(12位地址),尽管现代CPU可以选择映射更大的页面以减小映射表的大小 由于L2

我知道,使用C malloc和posix_memaligh可以从进程的虚拟地址空间分配连续内存。然而,我想知道人们是否能以某种方式分配一个物理上连续的内存缓冲区?我正在调查利用二级缓存的侧通道攻击,因此我希望确保能够访问正确的缓存线。

在(几乎[注1])所有虚拟内存架构上,虚拟内存都以“页面”为单位映射到物理内存。页面的大小(几乎)总是2的幂,并且页面按该大小对齐,因为映射仅通过使用地址的高阶位完成。页面大小通常为4K(12位地址),尽管现代CPU可以选择映射更大的页面以减小映射表的大小

由于
L2_CACHE_SIZE
通常也将是2的幂,并且将小于页面大小,因此大小
L2_CACHE_SIZE
的任何单个对齐分配都必须位于单个页面中,因此对齐中的字节也将是物理上连续的

因此,在这种特殊情况下,您可以确信分配的内存将是单个缓存线(至少在标准机器架构上)



注1:毫无疑问,有些机器——可能是虚构的——不以这种方式工作。但是你正在玩的不是它们中的一个。

你最好也是最容易使用连续内存的方法是从系统中请求一个“巨大”的页面。这些功能的可用性取决于您的CPU和内核选项(在x86_64上,通常可以使用2MB的巨大页面,一些CPU也可以使用1GB的页面;其他体系结构可能比这更灵活)。查看
/proc/meminfo
中的
Hugepagesize
字段,了解设置中的巨大页面大小

这些可通过两种方式访问:

  • 通过传递给
    mmap()
    MAP\u HUGETLB
    标志。通过这种方式,您可以确保“巨大”虚拟页面对应于一个连续的物理内存范围。不幸的是,内核是否能为您提供一个“巨大”页面取决于许多因素(内存利用率的当前布局、内核选项等-另请参见
    hugepages
    kernel boot参数)

  • 通过从专用的HugeTLB文件系统映射文件(请参见此处:)。使用HugeTLB文件系统,您可以提前配置可用的巨大页面数量,以确保必要数量的巨大页面可用


  • 另一种方法是编写一个内核模块,它将在内核端分配连续的物理内存,然后根据请求将其映射到进程的地址空间。这种方法有时用于嵌入式系统中的专用硬件。当然,仍然不能保证内核内存分配器能够提供适当大小的连续物理地址范围,因此在某些情况下,这些地址范围在引导时是预先保留的(一种愚蠢的方法是在引导时将
    max_addr
    参数传递给内核,使一些RAM超出内核的范围).

    可能值得检查POSIX接口、mmap等。我不知道这是否与侧通道攻击有很大区别。正如@gnasher729所说,它非常特定于操作系统,通常只有内核本身有任何理由需要担心物理地址。因此,我在这里要做的是使用POSIX_memalign to分配一个大小为L2_CACHE_size的块,我也会将该块与缓存线的大小对齐。因此,我在这里试图回答的问题是,我是否可以假设,既然分配的虚拟内存与缓存线的大小对齐,那么相应的物理内存将是连续的……在我的情况下,虚拟内存的大小二级缓存是256K,这肯定大于4K的页面大小。@Mimo:但您不需要物理上连续的内存;您只需要将单个缓存线分配为实际缓存线。二级缓存本身是单个缓存线的集合;两个相邻的缓存线是否映射相邻的物理(或虚拟)缓存线记忆是不相关的。