197
操作系统模型

在学习操作系统以及编译相关知识以及在CTF pwn题型实际应用中,笔者之前常常会陷入内存分段模型与平坦模型的区别与使用范围的纠结中。为了弄清内存分段、分页与平坦模型之间的区别以及相互联系和发展历史,笔者查阅了不少资料,也算对这个问题有了一个较好的解答。在此感谢前辈们的深入理解和分享精神。
  下面,让我们一起探求其中奥秘吧!

(本文主要为解答问题所需的概述,有不严谨之处敬请谅解)

内存的分段模型

故事还要从内存分段模型的产生说起……

产生

最初,在16位架构处理器上,由于一个寄存器只有16位,所以只能最高支持64KB的内存地址。而相对而言较好开发的内存则已经超过了1MB,那么如何在硬件层面(即仅通过硬件系统处理而不需要软件开发者考虑)让CPU可以访问到这1MB的内存空间呢?答案是使用两个寄存器

8086处理器通过引入分段机制,很好地解决了问题。该处理器拥有16位数据总线和20位地址总线,为了支持20位地址总线所能支持的最高1MB内存空间,处理器使用两个寄存器来表达一个地址——段基址寄存器和段内偏移寄存器。在地址处理单元中,接收到的段基址将被左移4位,再与段内偏移地址相加,最终得到一个20位的地址,供地址总线进行寻址。

额外优势

分段机制通过非常简单的操作,可以方便地实现程序的浮动与重定位。

在编写分段程序时,程序的每个段按照如下方法组织:

  • 每个段的汇编地址从0开始
  • 代码内使用段内偏移地址(而不是硬编码地址)

在程序加载后,可以得到程序各段在内存中的起始地址。将得到的段基址赋值给段寄存器,或在保护模式下构造段描述符,并将对应段选择子赋值给段寄存器,就可以实现程序的重定位。

内存分页机制

引入

进入32位(x86)架构处理器时代,引入了处理器的保护模式,程序仍通过分段机制访问内存,在保护模式中,段描述符定义了段的各个属性,如可读可执行,可读/写等,加强了段内存的安全性。但在程序较多或程序段碎片过多时,或是某段内存数据因为不常使用被换出,想换入却找不到合适的大小时,就暴露出仅使用分段模式的不足。

为了解决线性地址连续而对应物理地址不一定连续的问题,操作系统引入了内存分页机制。通过页表构建线性地址与物理地址的映射关系,让不连续的物理内存空间得到了很好的使用。

特点

  • 一般将线性空间划分为4KB大小的页,再将其分别对应到物理空间上
  • 如果程序需要使用某个地址上的数据,而对应页为空,则引发页错误(Page Fault)
  • 页错误转交操作系统,操作系统计算偏移,并建立物理页与逻辑页的映射关系
  • 分页机制有效避免了外部碎片与紧缩
  • 避免将不同大小的内存块匹配到交换空间(swap space)的问题
  • 页同样可以设置属性,与段描述符类似

分段机制的弱化

分段机制由数据总线向更宽地址总线的扩展而引入,带来了便捷的程序重定位优势,又通过段描述符增强其访问内存的安全性。然而,这些优势在日后处理器架构的变革和其他机制的引进中逐渐消失,分段机制也随之而式微……

处理器架构革新

进入x86架构时代,32位的数据总线和寄存器大小已经能够支持最高4GB的内存容量。在x86刚刚发展的时候,4GB的内存对当时的程序员来说已然是一个天文数字(有趣的是,如今,仅仅4GB内存的电脑已经不在主流市场的考虑范围之内,或许未来有一天,我们也会为“仅仅”2147483648GB大小的内存而感到发愁吧,XD)。CPU的数据/地址总线已经可以完整支持整个内存空间的寻址,而不需要再用“分段”的“将就”办法了。分段机制失去了其当初被引入的基础条件

分页机制的引入

通过引入分页机制,程序使用的线性地址可以被映射到物理地址,通过处理器完整总线的支持,线性地址可以访问所有内存空间。

为了简化内存管理模型,分页模型中限制了分段机制的作用,将一个进程的虚拟地址限制在4GB,也就是一个段的最大大小。

另外,分页也可以进行页属性的管理,同样可以提升内存安全性。

程序加载过程中,先进行分段,再将每个段进行分页映射。这样其实是没有必要的。一个程序最多能够使用4GB的内存空间,而一个段的最大空间也是4GB,所以可以省略分段的过程,只用分页进行一次映射就可以完成装载。这就可以引入内存平坦模型的概念。

平坦模型

基础

  1. 首先要明确,分段机制是x86架构的固有机制,是处理器的行为,即,处理器一定是按照[段机制+段偏移]来生成一个物理地址的。
  2. 平坦模型一定在分页机制下运行,分页机制是内存平坦模型的基础。

基本特点

  • 实质上,内存平坦模型没有分段,仅保留一个段,将原先各个段的数据都写入其中
  • 在操作上,仍然要构造段描述符(是固有机制),将所有段的段起始地址设为0,长度设为4G,粒度4KB,也就是,所有段都重合
  • 加载程序时,将程序一次性加载到线性地址空间中,同时创建页目录和页表,建立逻辑地址和物理地址的映射
  • 仍然可以划分各段,只是这里的划分没有在内存管理中发挥作用,仅在逻辑上将数据进行归纳分类。
  • 这些逻辑段的属性仍然被标出,在程序装载时,根据其属性被合并分配到不同的页中


原文地址:https://www.csdn.net/tags/MtTacg0sODE1Mi1ibG9n.html

【版权与免责声明】转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章,如 果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,烦请提供相关信息发邮件至387020@qq.com,我们将及时沟通与处理。


这条帮助是否解决了您的问题? 已解决 未解决

提交成功!非常感谢您的反馈,我们会继续努力做到更好! 很抱歉未能解决您的疑问。我们已收到您的反馈意见,同时会及时作出反馈处理!