程序如何分段?

时间:2012-04-28 05:20:18

标签: memory-management architecture memory-segmentation

如果这个问题被认为过于微不足道,我会事先道歉,但我确实花了很多时间试图在网上找到一个简单的答案而不能。

我最近在一个介绍编程类中读到了有关程序分段的问题,以及程序通常如何划分为“段”,这些段在需要时单独加载到内存中(或部分加载到内存中,通过分页...我认为)。我们的书中提到,程序通常根据逻辑划分划分为多个部分,例如:堆栈,堆,全局常量等的段

我想知道究竟是什么决定了这种细分的工作原理。它是在编译时由编译器完成的吗?或者操作系统以某种方式处理它?每个子程序通常都会得到自己的段,无论多小?

我知道与段描述符等分段相关的信息在架构级别使用寄存器处理,并且专门用于处理分段。但是,我在设想程序的实际分段在何处/如何发生以及这些信息如何进入这些寄存器时遇到了很多麻烦。地址如何转换为段ID和偏移量?任何人都可以开导我吗?非常感谢您提供的任何帮助,如果我在这里宰了任何概念,请对不起。

3 个答案:

答案 0 :(得分:1)

这是指可执行文件格式;正如其他人所指出的那样,链接器把它放在一起。

在我的OS X系统上,file /bin/ls报告/bin/ls: Mach-O universal binary with 2 architectures

接下来,您希望查找有关该格式的详细信息以及阅读这些格式的工具。 我认为,实际上看一下这些细分市场,会让你了解它们的内容以及它的结构。

从后一个链接:

  

每个Mach-O文件由一个Mach-O头组成,后跟一系列加载命令,后跟一个或多个段,每个段包含0到255个段。 Mach-O使用REL重定位格式来处理对符号的引用。查找符号时,Mach-O使用两级命名空间,将每个符号编码为“对象/符号名称”对,然后通过首先对象然后是符号名称进行线性搜索。

     

基本结构 - 引用文件中其他位置的数据页的可变长度“加载命令”列表 - 也用于Accent的可执行文件格式。反过来,Accent文件格式基于Spice Lisp的想法。

为了完整起见,其他操作系统的其他工具:

答案 1 :(得分:1)

这是一个很好的问题,我只能提供一些可能引导您朝着正确方向前进的信息。我相信程序分段是由可执行文件格式定义的,因此如果您需要特定信息,请查找本机格式的规范(例如,各种ELF变体)。阅读有关旧格式(如a.out或旧的“MZ”DOS二进制文件)的内容可能会很有趣,如果只是为了透视并且看到更简单的规范。 [已编辑:为清晰起见]

正如您似乎已经猜到的那样,分段由工具链(主要是链接器)协同处理,尽管编译器有一些影响:例如,全局C变量进入与局部变量不同的段,这些变量位于堆栈上和操作系统。有关操作系统参与的示例,良好的操作系统利用硬件平台的内存保护功能来强制正确使用程序的段。

希望这会为你提供进一步研究的材料。

答案 2 :(得分:1)

这里有一些基本的想法。

我们希望确保程序的代码和常量数据在运行时不会因其中的错误或利用它们的恶意输入而被修改。如果检测到尝试,操作系统应终止程序。好处:捕获错误,提高安全性。典型的实现机制:页面级内存保护。

我们通常也不希望程序中的任何数据区域可执行。恶意输入可以利用程序错误并导致在这些区域中执行任意(攻击者控制的)代码。相同的实施机制。

在读取/写入/执行不可访问的不同类型的程序部分(代码/常量,数据,堆栈)之间的内存(通常称为保护页面)中存在间隙可能会捕获一些缓冲区溢出错误,这可能会再次发生,有安全影响。有时在每个数据对象之前和之后放置这种特殊间隙。在生产代码中,它们太昂贵了(因为内存浪费和需要执行的额外代码来管理它们),但是在调试时它们可以提供很大的帮助。

代码和数据逻辑分离的另一个原因是共享库(例如DLL)。您的操作系统可以在不同进程之间共享(再次,通过使用页面转换)库代码,从而节省内存,同时在这些进程中维护单个数据区域。

当您阅读并理解页面翻译(包括所有页面表和虚拟到物理地址转换)时,您将学习如何实现所有这些目标。

最后,可能存在某些硬件限制,例如分段地址空间。这是x86 CPU的16位模式的情况。在这些模式下,即使您可以访问大约1MB的内存(在实际寻址模式和虚拟8086模式下)和16MB内存(在16位保护模式下),CPU也会强制您使用地址它被分成16位部分,段选择器和偏移量。在每个这样的段中,您最多只能访问65536个字节。如果您需要更多,则必须使用多个段,并且为了在段之间切换,您需要重新加载段寄存器以指向感兴趣的段。这种限制使得许多MSDOS汇编器和编译器生成对象(=部分编译)和可执行(=完全编译器)代码,各个程序部分之间有明确的边界,最明显的是代码和数据,每个不超过65536字节。