【发布时间】:2021-05-30 02:28:45
【问题描述】:
背景资料:
-
我在 x86 系统上使用 64 位 Arch。
-
我没有使用 libc 或任何依赖于 libc 的语言。我正在使用专有的研究语言。我正在通过内联汇编进行系统调用。
-
我正在为一个研究项目编写一个实验性的自定义分配器,所以一个可移植的解决方案是一个不错的选择,但不是必需的。
-
我的程序是静态链接的,我愿意并且能够重写我用来解决给定解决方案的库。
根据这个 SO 帖子:Where is the stack memory allocated from for a Linux process? 一个程序的虚拟地址空间是这样组织的:
------------------ <--- 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,上面写着:
对于 64 位进程,具有进程地址空间的两组地址范围可用于 mmap 或 shmat 映射。第一个由单个范围 0x07000000_00000000-0x07FFFFFF_FFFFFFFF 组成,可用于固定位置和可变位置映射。第二组地址范围仅可用于固定位置映射,包括范围 0x30000000-0xCFFFFFFF、0xE0000000-0xEFFFFFFF 和 0x10_00000000-0x06FFFFFF_FFFFFFFF。该集合的最后一个范围,由 0x10_00000000-0x06FFFFFF_FFFFFFFF 组成,也可供系统加载程序用于保存程序文本、数据和堆,因此只有该范围中未使用的部分可用于固定位置映射。
这正是我需要的信息,但它适用于错误的操作系统。如果有人可以帮助我找到有关 Linux 和 Arch 的相同信息,那将是一个很大的帮助。
【问题讨论】:
-
只要调用
mmap地址为NULL,内核就会选择一个合适的地址。 -
这就是我的其他自定义分配器的工作方式。这需要对事情的发展有自己的看法。
-
一种方法是在
mmap一个非常大的MAP_ANONYMOUS | MAP_NORESERVE区域前面,传递地址NULL让内核选择地址。然后您知道您可以在该地址区域内安全地创建MAP_FIXED映射。
标签: linux memory-management mmap allocation virtual-memory