我了解到一个进程在内存中具有以下结构:
(图片来自操作系统概念,第82页)
然而,我并不清楚是什么决定了一个流程是这样的。我猜进程可以(并且是这样做的?)如果你看一下非标准的操作系统/架构,看起来会有所不同。
这种结构是由操作系统决定的吗?被程序的编译器?通过计算机体系结构?它们的组合?
发布于 2019-04-19 18:27:58
相关的和可能的重复:Why do stacks typically grow downwards?。
在一些ISA(如x86)上,会出现一个向下增长的堆栈。(例如,call
在推送返回地址之前会递减SP/ESP/RSP,而异常/中断会将返回上下文推送到堆栈上,因此即使您编写了避免call
指令的低效代码,您也无法避免使用至少内核堆栈的硬件,尽管用户空间堆栈可以做您想做的任何事情。)
在其他情况下(比如没有隐式堆栈使用的MIPS ),这是一种软件约定。
布局的其余部分由此而来:您希望在堆栈向下增长和/或堆增长向上发生冲突之前,为它们提供尽可能多的空间。(或者允许您对他们的增长设置更大的限制。)
根据操作系统和可执行文件格式的不同,链接器可能会选择布局,比如文本位于BSS之上还是之下以及读写数据。OS的程序加载器必须考虑链接器请求加载部分的位置(至少对于支持静态代码/数据/BSS的ASLR的可执行文件而言是相对的)。通常,这类可执行文件使用PC相对寻址来访问静态数据,因此ASLRing相对于数据或bss的文本将需要运行时修正(而不是这样做)。
或者,依赖于位置的可执行程序将其所有段加载到固定(虚拟)地址,只有堆栈地址是随机化的。
“堆”通常不是真实的东西,特别是在具有虚拟内存的系统中,因此每个进程都可以有自己的私有虚拟地址空间。通常,您会为堆栈保留一些空间,并且在分配新页面时,malloc (实际上是它的底层mmap(MAP_ANONYMOUS)
系统调用)可以选择那些尚未映射的空间之外的所有内容。但是,是的,即使是现代Linux上的现代glibc的malloc
仍然使用brk()
向上移动小分配的“程序中断”,以图中显示的方式增加“堆”的大小。
发布于 2015-09-06 05:01:52
这个数字代表了一个具体的实现或者一个理想化的实现。流程不一定具有这种结构。在许多系统上,流程看起来只是有点类似于图中的流程。
发布于 2015-09-08 21:08:50
我认为这是一些委员会的建议,然后像GCC这样的工具就符合这个建议。二进制格式定义了这些段,操作系统及其工具促进了该格式的处理在系统上运行。假设ELF是由system V推荐的,然后被unix采用;由gcc制作在unix上运行的ELF二进制文件。所以我觉得故事可以从二进制格式开始,因为它决定了内存映射(代码,数据/堆/堆栈)。在其他hack中,二进制格式定义了加载程序时要映射的内存映射。例如,ELF定义段(将代码排列在文本、数据、堆栈中以加载到存储器中),当加载器加载这些段时,GCC生成ELF二进制段。操作系统还可以自由地调整这些段的值,如堆栈大小。这些是我试图巩固的有争议的响亮的想法。
https://stackoverflow.com/questions/32413193
复制相似问题