如何在程序中找到 MMAPable 虚拟地址的范围?

How do I find the range(s) of MMAPable virtual addresses in a program?

背景资料:

  1. 我在 x86 系统上使用 64 位 Arch。

  2. 我没有使用 libc 或任何依赖于 libc 的语言。我正在使用一种专有的研究语言。我正在通过内联汇编进行系统调用。

  3. 我正在为一个研究项目编写一个实验性自定义分配器,因此可移植解决方案是一个不错的选择,但不是必需的。

  4. 我的程序是静态链接的,我愿意并且能够重写我正在使用的库来说明给定的解决方案。

根据这个 SO post:Where is the stack memory allocated from for a Linux process? 一个程序的虚拟地址 space 是这样组织的:

------------------ <--- Top of the process address space
Stack (grows down)
v v v v v v v v v
------------------

(unmapped)

------------------ <--- Maximum stack size.


(unmapped)


-------------------
mmap
-------------------


(unmapped)


-------------------
^ ^ ^ ^ ^ ^ ^ ^ ^ ^
brk (grows up)
-------------------
BSS
-------------------
Data
-------------------
Text
-------------------

------------------- <--- Bottom or process address space.

假设这是正确的,我试图找到 brk 和堆栈之间的 MMAPable 地址范围。

通过从 sbrk(0) 获取 ptr,页面向上对齐 ptr,然后确保不再调用 brksbrk 是否足以找到下限?

通过获取堆栈上某个位置的 ptr 来安全地近似上限是否足够,从 getrlimit 中获取堆栈的最大大小,从 ptr 中减去它,页面向下对齐 ptr , 然后确保堆栈的大小永远不会被 setrlimit?

改变

我在这里不需要一个确切的范围,但我确实需要一个大的连续地址范围,这些地址保证是安全的 MMAPable(当然,假设我自己不破坏它们)。在我的研究过程中,我遇到了这个: https://www.ibm.com/docs/en/aix/7.2?topic=memory-understanding-mapping ,它说:

For 64-bit processes, two sets of address ranges with the process address space are available for mmap or shmat mappings. The first, consisting of the single range 0x07000000_00000000-0x07FFFFFF_FFFFFFFF, is available for both fixed-location and variable-location mappings. The second set of address ranges is available for fixed-location mappings only and consists of the ranges 0x30000000-0xCFFFFFFF, 0xE0000000-0xEFFFFFFF, and 0x10_00000000-0x06FFFFFF_FFFFFFFF. The last range of this set, consisting of 0x10_00000000-0x06FFFFFF_FFFFFFFF, is also made available to system loader to hold program text, data and heap, so only unused portions of the range are available for fixed-location mappings.

这正是我需要的信息,但它是错误的 OS。如果有人能帮我找到关于 Linux 的一般信息,特别是关于 Arch 的信息,那将是一个很大的帮助。

经过大量测试,我发现我在问题中提出的解决方案确实有效。我一直在使用 cat /proc/<pid>/maps 检查我的自定义分配器,它的行为符合我的预期。重申解决方案:

  1. 要找到下界,请使用 sbrk(0),确保 ptr 是页面对齐的,然后确保不再调用 brksbrk

  2. 为了安全地近似上界,用 getrlimit 找到堆栈大小,从 ptr 中减去它进入堆栈,页面对齐 ptr,然后永远不要用 setrlimit.

如果您可能需要触摸 brksbrksetrlimit,那么您还可以向下限添加一些填充并从上限减去一些填充。您可以通过查找系统具有 /proc/meminfo 的内存量来动态计算安全的填充量,或者如果您不需要通用解决方案,您可以根据您的情况过度估计您需要的数量正在做。