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

时间:2015-09-05 12:43:48

标签: process compilation operating-system computer-architecture convention

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

enter image description here

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

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

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

3 个答案:

答案 0 :(得分:2)

相关且可能重复的内容:Why do stacks typically grow downwards?

在某些ISA(例如x86)上,放入向下增长的堆栈。(例如,call在推回地址之前递减SP / ESP / RSP,并且异常/中断将返回上下文推入堆栈因此,即使您编写的效率低下的代码避免了call指令,尽管用户空间堆栈可以做您想做的任何事情,但您至少不能逃避内核堆栈的硬件使用。)

在其他情况下(例如没有隐式堆栈使用的MIPS),这是一种软件约定。


其余的布局由此得出:在堆栈向下和/或堆栈向上冲突之前,您需要尽可能大的空间。 (或者允许您为它们的增长设置更大的限制。)

根据操作系统和可执行文件的格式,链接器可能会选择布局,例如文本是在BSS之上还是之下以及是读写数据。操作系统的程序加载器必须考虑链接器在何处加载段(至少相对于彼此,对于支持其静态代码/数据/ BSS的ASLR的可执行文件)。通常,此类可执行文件使用PC相对寻址来访问静态数据,因此将文本相对与数据或bss关联起来会需要运行时修复(并且没有完成)。

或依赖于位置可执行文件将其所有段加载到固定(虚拟)地址,并且只有堆栈地址是随机的。

“堆”通常不是真正的东西,尤其是在具有虚拟内存的系统中,因此每个进程可以拥有自己的私有虚拟地址空间。通常,您为堆栈保留了一些空间,并且尚未分配的所有内容都是公平的,可以在分配新页面时选择malloc(实际上是其基础的mmap(MAP_ANONYMOUS)系统调用)。但是,是的,即使是现代Linux上的现代glibc的malloc仍然使用brk()来向上移动“程序中断”以进行少量分配,从而增加了图表显示方式的“堆”大小。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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