【问题标题】:Questions about the Linux program memory layout schema关于Linux程序内存布局架构的问题
【发布时间】:2017-06-20 07:52:06
【问题描述】:

下图引自书Programming from the Ground Up

  • 为什么程序内存区域被限制在0xbfffffff0x8048000之间?这种选择背后的理由是什么?这个区域之外有什么?

  • 这张图片说明的应该是一个32位的程序。 64位程序的内存布局是什么?

  • 图片中提到了“at startup”,那么运行时布局会不会发生变化?

  • 最后但并非最不重要的一点是,Linux 内核是否也遵循这种布局?

【问题讨论】:

    标签: linux memory-management linux-kernel


    【解决方案1】:
    • 32 位 x86 上的 Linux 传统上具有 3G/1G 用户/内核拆分。

      • 用户空间内存始终映射在 0x00000000-0xBFFFFFFF 范围内(即,可以在 32 位模式下直接寻址的 4GB 中较低的 3GB)。在进程之间切换时会重新映射整个空间。

      • 内核内存始终映射在 0xC0000000-0xFFFFFFFF 范围内(上 1GB)。它在用户空间的特权级别是不可访问的,但是当上下文切换到内核时,它可以访问其所有内存而无需重新映射任何内容。

      我有一个older answer 对此进行了更详细的介绍。

    • 在 x86 上,堆栈向下增长(从高处开始向低地址移动)。这几乎是 CPU 设计中的任意决定(这就是 push/pop/call/ret 指令对 %esp 所做的事情)。 Linux 在范围的顶部启动它。

      相比之下,程序数据默认映射到低端。从历史上看,内核映射在0x08000000 之下,因此用户空间可用的最低地址在其之上。这不再是真的,但它解释了原来的0x08040000 加载地址。

    • 中间的空间用于堆。 “中断”标记通过调用brk()sbrk() 向上/向下移动;它下面的内存可供程序使用。从历史上看,C 运行时移动程序分解以满足malloc 的空间要求。

    • 在当前的 64 位 x86 CPU 上,只有地址 0x0000000000000000-0x00007FFFFFFFFFFF 和 0xFFFF800000000000-0xFFFFFFFFFFFFFFFF 是规范的。 64 位指针,但“仅”48 位可用地址空间。 (这是 256TB,因此我们需要一段时间才能达到该限制。)如果您尝试访问任何非规范地址(0x0000800000000000-0xFFFF7FFFFFFFFFFF),硬件将触发故障。 Linux 在下半部分映射用户空间,在上半部分映射内核。

      堆栈仍然向下增长,因此 Linux 仍然从范围顶部开始,固定映射从底部开始,堆在它们上方增长。

    • 是的。除了随着堆的增长和缩小而上下移动的程序中断,程序还可以使用mmap/munmap将各种东西映射/取消映射到它的地址空间,例如文件、共享内存、匿名内存、等等。事实上,如今的 C 运行时除了或代替操纵程序中断之外,还以块的形式映射匿名内存。

    • 内核本身在 32 位 x86 上位于上层 1G,在 64 位 x86 上位于上层 128TB。它的布局对用户空间几乎不重要(并且不可见),但包括诸如每个内核线程的堆栈和每个用户线程的内核端、页表、缓存、DMA 缓冲区等。

    其他说明:

    所有这些都是关于虚拟地址,而不是物理地址。

    用户空间可访问的最低地址不一定是 0。C 程序期望 NULL 是一个错误地址(如果它实际上是有效的,这可能会导致 exploits),并且内核强制执行 /proc/sys/vm/mmap_min_addr,它默认为现在 64k。

    现在的Linux(现在已经十多年了)将VDSO 映射到一个极高的地址,因此堆栈从该地址下方开始。曾几何时,vsyscall 页面也在上面,但现在它位于内核空间的页面中。

    由于ASLR,所有地址可能会被打乱。这在 32 位地址空间上不是很有效(由于页面对齐,您不能随机化低 12 位,可能更多是由于其他限制),但是在 64 位模式下有很多位。

    【讨论】:

    • 我有另一个old answer 涉及初始堆栈布局。 Linux 使用堆栈上的环境变量和命令行参数启动所有程序,C 运行时安排在 main() 之前。
    猜你喜欢
    • 2011-09-29
    • 2016-12-15
    • 2013-05-24
    • 1970-01-01
    • 2013-07-12
    • 2013-03-07
    • 2011-05-22
    • 2019-08-21
    相关资源
    最近更新 更多