- 如果将整个地址空间放入物理内存,那么栈和堆之间的空间并没有被进程使用,确依然占用了实际的物理内存
利用MMU实现的虚拟内存很浪费。而且,如果剩余物理内存无法提供连续区域来放置完整的地址空间,进程便无法运行。
16.1 分段:泛化的基址/界限
- 在MMU中引入不止一个基址和界限寄存器对,而是给地址空间内的每个逻辑段一对。
一个端只是地址空间里的一个连续定长的区域,在典型的地址空间里有3个逻辑不同的段:代码、栈和堆
分段的机制使得操作系统能够将不同的短放到不同的物理内存区域,从而避免了虚拟地址空间中的未使用部分占用物理内存
只有已用内存才在物理内存中分配空间,因此可以容纳巨大的地址空间,其中包含大量的未使用的地址空间(优势又被称为系数地址空间)
Hint:编程时经常遇到Segmentation Fault……
16.2 引用哪个段
硬件在地址转换时使用段寄存器,通过显式方式获知段内偏移量和地址引用了哪个段:用虚拟地址的开头几位来标识不同的段。
上图是14位虚拟地址的前两位来标识3个段。使用两位来区分三个段,会造成一个段的地址空间被浪费,因此有些系统会将堆和栈当做同一个段,于是只需要一位做标识便可。
16.3 栈怎么办
由于栈是向上增长的。所以地址转换必须有所不同。
- 除了基址和界限外,硬件还需要直到段的增长方向(用一位区分,比如1标识从小到大,0反之)
16.4 支持共享
- 为了节省内存,有时要在地址空间之间共享某些内存段
为每个段增加几个位作为保护位,标识程序是否能够读写该段,或执行其中的代码
- 问题:会导致外部碎片
在这个例子中,一个进程需要分配一个20KB的段,当前有24KB的空闲,但并不连续。因此,OS无法满足这个20KB的请求。