Tim*_*Tim 5 linux process virtual-memory
我尝试从以下两个来源找出共享内存段的范围,即进程内存布局中的内存映射段。
从https://manybutfinite.com/post/anatomy-of-a-program-in-memory/,我找到了一个进程的内存布局图
内存映射段和堆会一直增长直到它们相遇吗?
或者两个段中的每一个都有一个限制,类似于堆栈段的 RLIMIT_STACK?
来自 Linux 编程接口
为了为堆和堆栈增长留出空间,共享内存段从虚拟地址 0x40000000 开始附加。映射映射(第 49 章)和共享库(第 41 和 42 章)也放置在该区域中。(根据内核版本和进程的 RLIMIT_STACK 资源限制的设置,共享内存映射和内存段的默认位置有一些变化。)地址 0x40000000 被定义为内核常量 TASK_UNMAPPED_BASE。
共享内存段是否从 TASK_UNMAPPED_BASE 开始并向上增长?
请注意,上图显示共享内存段向下增长,那么它是向上增长还是向下增长?
谢谢。
有一些限制适用于mmap段和堆段。RLIMIT_AS总体上确定可用的地址空间;这涵盖了程序可以进行的所有内存分配。RLIMIT_DATA确定数据段的最大大小。
内核根据这些限制检查堆栈扩展、mmap和brk(堆分配)。它还针对潜在的冲突段检查分配,因此这些段永远不会最终相互覆盖(例如,brk请参阅使用对堆分配执行的检查)。如果分配是不可能的,程序会得到适当的“通知”:C 库为 返回一个ENOMEM错误brk,SIGSEGV如果堆栈无法扩展,内核会用一个终止程序...
共享内存段(严格来说,从内核的角度来看,虚拟内存区域)如何增长取决于内存布局,它可以从一个进程到另一个进程。在大多数架构上,“传统”内存映射导致自底向上分配,从TASK_UNMAPPED_BASE;非遗留内存映射导致自上而下的分配。见arch_pick_mmap_layout()并且mmap_is_legacy()在x86架构中的一个例子。您可以使用setarch's-L标志切换到旧内存映射(请参见下面的示例)。
在实践中,您可以通过查看/proc/$$/maps和检查加载的共享库(如果有)的地址,以及它们的加载顺序来了解段是如何增长的。动态链接器总是首先加载;如果它的地址比其他库低,那么分配是自下而上的,否则是自上而下的。比较64 位 x86 系统上的cat /proc/self/maps和输出setarch x86_64 -L cat /proc/self/maps。