如何在程序中找到 MMAPable 虚拟地址的范围?
How do I find the range(s) of MMAPable virtual addresses in a program?
背景资料:
我在 x86 系统上使用 64 位 Arch。
我没有使用 libc 或任何依赖于 libc 的语言。我正在使用一种专有的研究语言。我正在通过内联汇编进行系统调用。
我正在为一个研究项目编写一个实验性自定义分配器,因此可移植解决方案是一个不错的选择,但不是必需的。
我的程序是静态链接的,我愿意并且能够重写我正在使用的库来说明给定的解决方案。
根据这个 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,然后确保不再调用 brk
和 sbrk
是否足以找到下限?
通过获取堆栈上某个位置的 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
检查我的自定义分配器,它的行为符合我的预期。重申解决方案:
要找到下界,请使用 sbrk(0)
,确保 ptr 是页面对齐的,然后确保不再调用 brk
和 sbrk
。
为了安全地近似上界,用 getrlimit
找到堆栈大小,从 ptr 中减去它进入堆栈,页面对齐 ptr,然后永远不要用 setrlimit
.
如果您可能需要触摸 brk
、sbrk
或 setrlimit
,那么您还可以向下限添加一些填充并从上限减去一些填充。您可以通过查找系统具有 /proc/meminfo
的内存量来动态计算安全的填充量,或者如果您不需要通用解决方案,您可以根据您的情况过度估计您需要的数量正在做。
背景资料:
我在 x86 系统上使用 64 位 Arch。
我没有使用 libc 或任何依赖于 libc 的语言。我正在使用一种专有的研究语言。我正在通过内联汇编进行系统调用。
我正在为一个研究项目编写一个实验性自定义分配器,因此可移植解决方案是一个不错的选择,但不是必需的。
我的程序是静态链接的,我愿意并且能够重写我正在使用的库来说明给定的解决方案。
根据这个 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,然后确保不再调用 brk
和 sbrk
是否足以找到下限?
通过获取堆栈上某个位置的 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
检查我的自定义分配器,它的行为符合我的预期。重申解决方案:
要找到下界,请使用
sbrk(0)
,确保 ptr 是页面对齐的,然后确保不再调用brk
和sbrk
。为了安全地近似上界,用
getrlimit
找到堆栈大小,从 ptr 中减去它进入堆栈,页面对齐 ptr,然后永远不要用setrlimit
.
如果您可能需要触摸 brk
、sbrk
或 setrlimit
,那么您还可以向下限添加一些填充并从上限减去一些填充。您可以通过查找系统具有 /proc/meminfo
的内存量来动态计算安全的填充量,或者如果您不需要通用解决方案,您可以根据您的情况过度估计您需要的数量正在做。