• 如果将整个地址空间放入物理内存,那么栈和堆之间的空间并没有被进程使用,确依然占用了实际的物理内存

利用MMU实现的虚拟内存很浪费。而且,如果剩余物理内存无法提供连续区域来放置完整的地址空间,进程便无法运行。

16.1 分段:泛化的基址/界限

  • 在MMU中引入不止一个基址和界限寄存器对,而是给地址空间内的每个逻辑段一对

一个端只是地址空间里的一个连续定长的区域,在典型的地址空间里有3个逻辑不同的段:代码、栈和堆

分段的机制使得操作系统能够将不同的短放到不同的物理内存区域,从而避免了虚拟地址空间中的未使用部分占用物理内存

image.png

只有已用内存才在物理内存中分配空间,因此可以容纳巨大的地址空间,其中包含大量的未使用的地址空间(优势又被称为系数地址空间)

image.png

Hint:编程时经常遇到Segmentation Fault……

16.2 引用哪个段

硬件在地址转换时使用段寄存器,通过显式方式获知段内偏移量和地址引用了哪个段:用虚拟地址的开头几位来标识不同的段。

image.png

上图是14位虚拟地址的前两位来标识3个段。使用两位来区分三个段,会造成一个段的地址空间被浪费,因此有些系统会将堆和栈当做同一个段,于是只需要一位做标识便可。

16.3 栈怎么办

由于栈是向上增长的。所以地址转换必须有所不同。

  • 除了基址和界限外,硬件还需要直到段的增长方向(用一位区分,比如1标识从小到大,0反之)

16.4 支持共享

  • 为了节省内存,有时要在地址空间之间共享某些内存段

为每个段增加几个位作为保护位,标识程序是否能够读写该段,或执行其中的代码


  • 问题:会导致外部碎片

image.png

在这个例子中,一个进程需要分配一个20KB的段,当前有24KB的空闲,但并不连续。因此,OS无法满足这个20KB的请求。
image.png