Memory management 一个项目是如何细分的?

Memory management 一个项目是如何细分的?,memory-management,architecture,memory-segmentation,Memory Management,Architecture,Memory Segmentation,如果这个问题被认为太琐碎,我提前表示歉意,但我确实花了大量时间试图在网上找到一个直截了当的答案,但无法做到 最近,我在一节编程入门课上读到了关于程序分段的内容,以及程序通常如何划分为“段”,在需要时单独加载到内存中(或者通过分页……我认为是部分加载到内存中)。我们的书中提到,程序通常根据逻辑划分划分为段,例如堆栈段、堆段、全局常量段等 我想知道到底是什么决定了这种细分的工作方式。它是由编译器在编译时完成的吗?还是操作系统能以某种方式处理它?是否每个子程序都有自己的段,不管它有多小 我知道,与分段

如果这个问题被认为太琐碎,我提前表示歉意,但我确实花了大量时间试图在网上找到一个直截了当的答案,但无法做到

最近,我在一节编程入门课上读到了关于程序分段的内容,以及程序通常如何划分为“段”,在需要时单独加载到内存中(或者通过分页……我认为是部分加载到内存中)。我们的书中提到,程序通常根据逻辑划分划分为段,例如堆栈段、堆段、全局常量段等

我想知道到底是什么决定了这种细分的工作方式。它是由编译器在编译时完成的吗?还是操作系统能以某种方式处理它?是否每个子程序都有自己的段,不管它有多小


我知道,与分段相关的信息(如分段描述符等)在体系结构级别通过寄存器进行处理,这些寄存器专门分配用于处理分段。但我只是很难想象程序的实际分段首先发生在哪里/如何发生,以及这些信息如何进入这些寄存器。如何将地址转换为段ID和偏移量?谁能启发我?非常感谢您提供的任何帮助,如果我在这里断送了任何概念,请原谅。

这是指可执行文件格式;正如其他人所注意到的,链接器将这一点放在一起

在我的OS X系统上,
file/bin/ls
报告
/bin/ls:Mach-O通用二进制文件,具有两种体系结构

接下来,您需要查找有关该格式的详细信息,以及读取这些信息的工具。 事实上,我认为,看看这些片段会让你对其中的内容及其结构有一个很好的了解

从后一个环节:

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

基本结构——引用文件中其他地方数据页的可变长度“加载命令”列表——也在可执行文件格式中用于强调。重音文件格式又是基于Spice-Lisp的一个想法

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

  • Linux二进制文件通常是格式化的:请参阅
    readelf--segments
    命令

  • Windows是-请参阅(商业版)


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

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


希望这将为您提供一些进一步研究的资料。

这里有一些基本的想法

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

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

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

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

当您阅读和理解页面转换(使用所有这些页面表和虚拟到物理地址转换)时,您将了解如何实现所有这些

最后,可能存在某些硬件限制,例如分段地址空间。x86 CPU的16位模式就是这种情况。在这些模式下,即使您可以访问高达1MB的内存(在实寻址模式和虚拟8086模式下)和16MB的内存(在16位保护模式下),CPU也会强制您使用分为16位部分的地址、段选择器和偏移量。在每个这样的段中,您最多只能访问65536个字节。如果您需要更多,您必须使用多个段,以便在segme之间切换