有关可执行程序(进程)的内存布局的更多信息

Posted

技术标签:

【中文标题】有关可执行程序(进程)的内存布局的更多信息【英文标题】:more info on Memory layout of an executable program (process) 【发布时间】:2010-12-30 07:55:00 【问题描述】:

我参加了三星的面试。他们问了很多关于程序内存布局的问题。我对此几乎一无所知。

我用谷歌搜索了“可执行程序的内存布局”。 “进程的内存布局”。

我很惊讶地发现关于这些主题的信息并不多。大多数结果是论坛查询。我只是想知道为什么?

这些是我找到的几个链接:

    Run-Time Storage Organization Run-Time Memory Organization Memory layout of C process^pdf^

我想从一本合适的书而不是一些网络链接中学习这一点。(兰迪海德的书也是一本书,但其他书)。我可以在哪本书中找到关于这个主题的清晰和更多信息?

我也想知道,为什么操作系统的书没有在他们的书中介绍这个?我读了stallings第6版。它只是讨论了过程控制块。

整个布局的创建是linker的任务对吧?我在哪里可以阅读有关此过程的更多信息。我想要从磁盘上的程序到处理器上执行的COMPLETE信息。

编辑:

最初,即使在阅读了下面给出的答案后,我也不清楚。最近,我读了这些文章,我明白了。

帮助我理解的资源:

    www.tenouk.com/Bufferoverflowc/Bufferoverflow1b.html 5部分PE文件格式教程:http://win32assembly.online.fr/tutorials.html 优秀文章:http://www.linuxforums.org/articles/understanding-elf-using-readelf-and-objdump_125.html PE 资源管理器:http://www.heaventools.com/

是的,“可执行程序的布局(PE/ELF)”!=“进程的内存布局”)。在第 3 个链接中自行查找。 :)

清除我的概念后,我的问题让我看起来很愚蠢。 :)

【问题讨论】:

这在 DOS、Windows 和 Unix 之间会有所不同,在 Unix 的不同风格之间也可能有所不同。你应该更具体 我不在乎那个“有点”。学习一个操作系统应该概述所有其他操作系统,对吗?无论如何,我会选择 WINDOWS。 无法访问 linuxforums 数据库。请稍后再试 链接 2 和 3 已损坏 【参考方案1】:

汇编编程艺术http://homepage.mac.com/randyhyde/webster.cs.ucr.edu/www.artofasm.com/Windows/PDFs/MemoryAccessandOrg.pdf

【讨论】:

Http/1.1 服务不可用【参考方案2】:

加载方式在很大程度上取决于操作系统和使用的二进制格式,而且细节可能会令人讨厌。二进制文件的布局有标准,但进程的内存布局实际上取决于操作系统。这可能是文档很难找到的原因。

回答您的问题:

    书籍: 如果您对进程如何布置内存感兴趣,请查看Understanding the Linux Kernel。第 3 章讨论了进程描述符、创建进程和销毁进程。 我所知道的唯一一本详细介绍链接和加载的书是 John Levine 的 Linkers and Loaders。有在线版和印刷版,请查看。

    可执行代码由编译器和链接器创建,但链接器将事物以操作系统所需的二进制格式放置。在 Linux 上,此格式通常为 ELF,在 Windows 和较旧的 Unix 上为 COFF,在 Mac OS X 上为 Mach-O。不过,这不是一个固定的列表。一些操作系统可以并且确实支持多种二进制格式。链接器需要知道输出格式才能创建可执行文件。

    进程的内存布局与二进制格式非常相似,因为很多二进制格式都被设计成mmap'd,这样加载器的任务就更容易了。

    这并不是相当那么简单。二进制格式的某些部分(如静态数据)不直接存储在二进制文件中。相反,二进制文件只包含这些部分的大小。当进程加载到内存中时,加载器知道分配正确的内存量,但二进制文件不需要包含大的空部分。

    此外,进程的内存布局包括一些空间供stack 和heap 使用,进程的调用帧和动态分配的内存都在其中。它们通常位于大地址空间的两端。

这实际上只是触及了如何加载二进制文件的皮毛,并没有涉及任何关于动态库的内容。要详细了解动态链接和加载的工作原理,请阅读How to Write Shared Libraries。

【讨论】:

因此,CONSTANTS 存储在 -- 部分。 GLOBAL 变量存储在 -- 部分。 STATIC 变量存储在 -- 部分等中。是否依赖于操作系统? how such sections r available? what are they? which content goes into what section? 没有任何标准吗?如果没有任何标准。为什么人们会问这样的问题(尤其是在面试中):( 这是二进制格式的标准,但就流程布局而言不是标准。如果您有兴趣了解其中的内容,请查看 ELF 或其他一些二进制规范。 好的,1. 如果它们是标准的,我在哪里可以找到这些信息? 2. 如果就 binary format 而言它们是标准的,那么不同的两件事是 a)如何将此二进制文件转换为可执行文件(文件格式发挥作用)和 b)此格式文件如何被加载到内存中(加载器的任务)。但是内存中的 final 布局应该是固定的。换句话说,它包含那些相同的部分(它们是标准的)并且它们包含 standard 内容。对吗? 1.在二进制规范中。 2a。二进制可执行文件(或库,几乎就像一个可执行文件)。 2b。内存中的最终布局取决于操作系统,但大多是标准的。加载程序在将进程或库放入内存时必须修复对符号的引用。再次,查看 Linux 内核书籍以了解进程布局的一般概述。查看如何编写共享库以获得关于运行时链接器/加载器如何将符号引用解析为这些符号实际存在于内存中的位置的非常详细的描述。 好吧,我完全糊涂了。我认为这对我更好,如果我在阅读您建议的内容后回到这个线程。【参考方案3】:

这是从文件 (*nix) 执行程序的一种方法。

进程已创建(例如 fork())。这为新进程提供了自己的内存映射。这包括某个内存区域中的堆栈(通常在某处内存的高处)。 新进程调用 exec() 以用新的可执行文件替换当前的可执行文件(通常是 shell)。通常,新的可执行文件 .text(可执行代码和常量)和 .data(r/w 初始化变量)是为需求页面映射设置的,即根据需要将它们映射到进程内存空间中。通常,.text 部分首先出现,然后是 .data。 .bss 部分(未初始化的变量)通常在 .data 部分之后分配。很多时候,当第一次访问包含 bss 变量的页面时,它被映射为返回一页零。堆通常在 .bss 部分之后的下一页边界处开始。然后堆在内存中增长,而堆栈在下降(记住我通常说过,有例外!)。

如果堆和堆栈发生冲突,通常会导致内存不足的情况,这就是堆栈经常被放置在高内存中的原因。

在没有内存管理单元的系统中,请求分页通常不可用,但经常使用相同的内存布局。

【讨论】:

解释得很好。

以上是关于有关可执行程序(进程)的内存布局的更多信息的主要内容,如果未能解决你的问题,请参考以下文章

OS-103

Linux_Unix系统编程chapter6 进程

进程查看和进程管理

线程进程与协程

程序与进程的关系

程序员的自我修养-链接装载与库-6 可执行文件的装载与进程