是什么决定了一个进程在内存中的结构?

问题描述 投票:1回答:3

我了解到一个进程在内存中具有以下结构:

enter image description here

(图82来自操作系统概念,第82页)

但是,我不清楚是什么决定一个过程看起来像这样。如果你看一下非标准的操作系统/架构,我想进程可以(并且确实如此)看起来不同。

这个结构是由OS决定的吗?通过程序的编译器?通过计算机架构?这些组合?

process compilation operating-system computer-architecture convention
3个回答
2
投票

相关和可能的重复:Why do stacks typically grow downwards?

在一些ISA(如x86)中,向下扩展堆栈。(例如,call在推送返回地址之前递减SP / ESP / RSP,异常/中断将返回上下文推送到堆栈,因此即使您编写了低效的代码虽然用户空间堆栈可以做任何你想做的事情,但是避免使用call指令,你至少无法逃避内核堆栈的硬件使用。)

在其他方面(如没有隐式堆栈使用的MIPS),它是一个软件约定。


其余的布局遵循以下内容:在碰撞之前,您需要尽可能多的空间用于向下堆栈增长和/或向上堆增长。 (或允许您对其增长设置更大的限制。)

根据操作系统和可执行文件格式,链接器可以选择布局,例如文本是高于还是低于BSS和读写数据。 OS的程序加载器必须尊重链接器要求加载段的位置(至少相对于彼此,对于支持其静态代码/数据/ BSS的ASLR的可执行文件)。通常,此类可执行文件使用PC相对寻址来访问静态数据,因此相对于数据或bss对文本进行ASLR操作将需要运行时修复(并且未完成)。

或者位置相关的可执行文件将其所有段加载到固定(虚拟)地址,只有堆栈地址随机化。

“堆”通常不是真实的,尤其是在具有虚拟内存的系统中,因此每个进程都可以拥有自己的私有虚拟地址空间。通常你会为堆栈预留一些空间,而且那些尚未映射的空间之外的所有东西都是malloc(实际上它的底层mmap(MAP_ANONYMOUS)系统调用)的公平游戏,可以在分配新页面时选择。但即使是现代Linux上的现代glibc的malloc仍然使用brk()将“程序中断”向上移动以进行小分配,以图表的方式增加“堆”的大小。


0
投票

我认为这是由一些委员会推荐的,然后像GCC这样的工具符合该建议。二进制格式定义了这些段,操作系统及其工具便于该格式在系统上运行。让我们说ELF是系统V推荐的,然后由unix采用;和gcc生成要在unix上运行的ELF二进制文件。所以我觉得故事可能从二进制格式开始,因为它决定了内存映射(代码,数据/堆/堆栈)。除了其他黑客之外,二进制格式定义了为加载程序而映射的内存映射。例如,ELF定义了段(将文本,数据,堆栈中的代码排列在内存中),GCC在加载器加载这些段时生成ELF二进制段。操作系统也可以自由调整这些段的值,如堆栈大小。这些是有争议的响亮的想法,我试图巩固。


0
投票

该图表示特定实现或理想化实现。流程不一定具有该结构。在许多系统中,进程看起来有点类似于图中的内容。

© www.soinside.com 2019 - 2024. All rights reserved.