简体   繁体   English

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

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

Background information:背景资料:

  1. I'm using 64 bit Arch on an x86 system.我在 x86 系统上使用 64 位 Arch。

  2. I'm not using libc or any language that depends on libc.我没有使用 libc 或任何依赖于 libc 的语言。 I'm using a proprietary research language.我正在使用专有的研究语言。 I am making my syscalls through inline assembly.我正在通过内联汇编进行系统调用。

  3. I'm writing an experimental custom allocator for a research project, so a portable solution is a nice-to-have, but not a requirement.我正在为一个研究项目编写一个实验性的自定义分配器,所以一个可移植的解决方案是一个不错的选择,但不是必需的。

  4. My programs are statically linked and I am willing and able to rewrite the libraries I'm using to account for a given solution.我的程序是静态链接的,我愿意并且能够重写我用来解释给定解决方案的库。

According to this SO post: Where is the stack memory allocated from for a Linux process?根据此 SO 帖子: 为 Linux 进程分配的堆栈 memory 在哪里? A program's virtual address space is organized like this:程序的虚拟地址空间是这样组织的:

------------------ <--- 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.

Presuming this is correct, I'm trying to find the range of MMAPable addresses between brk and the stack.假设这是正确的,我试图找到 brk 和堆栈之间的 MMAPable 地址范围。

Is it sufficient to find the lower bound by getting a ptr from sbrk(0) , page aligning the ptr upwards, and then ensuring that brk and sbrk are never called again?通过从sbrk(0)获取 ptr,向上对齐 ptr,然后确保不再调用brksbrk来找到下限是否足够?

Is it sufficient to safely approximate the upper bound by getting a ptr to some location on the stack, getting the max size of the stack from getrlimit , subtracting that from the ptr, page aligning the ptr downwards, and then ensuring the size of the stack is never changed by setrlimit ?通过将 ptr 获取到堆栈上的某个位置,从getrlimit获取堆栈的最大大小,从 ptr 中减去它,将 ptr 向下对齐,然后确保堆栈的大小,是否足以安全地逼近上限?永远不会被setrlimit改变?

I don't need an exact range here, but I do need a large contiguous range of addresses that are guaranteed to be safely MMAPable(presuming I don't clobber them myself, of course).我在这里不需要一个确切的范围,但我确实需要一个大范围的连续地址,这些地址可以保证是安全的 MMAPable(当然,假设我自己没有破坏它们)。 During my research I came across this: https://www.ibm.com/docs/en/aix/7.2?topic=memory-understanding-mapping , which says:在我的研究中,我遇到了这个: 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.对于 64 位进程,具有进程地址空间的两组地址范围可用于 mmap 或 shmat 映射。 The first, consisting of the single range 0x07000000_00000000-0x07FFFFFF_FFFFFFFF, is available for both fixed-location and variable-location mappings.第一个由单个范围 0x07000000_00000000-0x07FFFFFF_FFFFFFFF 组成,可用于固定位置和可变位置映射。 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.第二组地址范围仅可用于固定位置映射,包括范围 0x30000000-0xCFFFFFFF、0xE0000000-0xEFFFFFFF 和 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.该集合的最后一个范围由 0x10_00000000-0x06FFFFFF_FFFFFFFF 组成,也可供系统加载程序用于保存程序文本、数据和堆,因此只有该范围的未使用部分可用于固定位置映射。

This is the exact kind of information I need, but it's for the wrong OS.这是我需要的确切信息,但它适用于错误的操作系统。 If anyone can help me find this same information about Linux in general and Arch specifically, then that would be a great help.如果有人可以帮助我找到有关 Linux 和 Arch 的相同信息,那将是一个很大的帮助。

After a lot of testing I've found the solution I proposed in the question does work.经过大量测试后,我发现我在问题中提出的解决方案确实有效。 I've been using cat /proc/<pid>/maps to check my custom allocator, and it's behaving as I expected.我一直在使用cat /proc/<pid>/maps来检查我的自定义分配器,它的行为符合我的预期。 To reiterate the solution:重申解决方案:

  1. To find the lower bound use sbrk(0) , make sure the ptr is page aligned, and then ensure that brk and sbrk are never called again.要找到下限,请使用sbrk(0) ,确保 ptr 是页面对齐的,然后确保不再调用brksbrk

  2. To safely approximate the upper bound find the stack size with getrlimit , subtract that from a ptr into the stack, page align the ptr, and then never change the stack size with setrlimit .为了安全地近似上限,使用getrlimit找到堆栈大小,从 ptr 中减去堆栈大小,对 ptr 进行页面对齐,然后永远不要使用setrlimit更改堆栈大小。

If you might need to touch brk , sbrk , or setrlimit , then you can also add some padding to the lower bound and subtract some padding from the upper bound.如果您可能需要触摸brksbrksetrlimit ,那么您还可以在下限中添加一些填充并从上限中减去一些填充。 You can dynamically compute a safe amount of padding by finding how much memory the system has with /proc/meminfo , or if you don't need a general solution you can just over-approximate how much you'll need based on what you're doing.您可以通过使用/proc/meminfo找到系统有多少 memory 来动态计算安全的填充量,或者如果您不需要通用解决方案,您可以根据您的需要过度估计您需要多少重新做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM