第四章 非连续内存分配
一、为什么需要非连续内存分配
1、连续内存分配
分配给一个程序的物理内存是连续的。
缺点:内存利用率低、存在内碎片、外碎片的问题。
2、非连续内存分配
分配给一个程序的物理地址空间是非连续的。
优点:更好的内存利用和管理、允许共享代码与数据、支持动态加载和动态链接。
缺点:带来额外的管理开销:如何建立虚拟地址和物理地址之间的转换。两种实现:软件方案和硬件方案。
两种硬件方案:分段、分页。
二、分段、分页寻址
计算机的程序其实是由各种各样的段组成的,不同的段之间有不同的属性,比如主程序、子程序、各种库等。数据有栈段、堆段,共享数据段等。所谓分段,就是根据应用程序不同段的特点,将它们区别出来,进行分离、管理。
逻辑地址空间虽然是连续的,但通过一些特定的方法,把各种段分离出来,它们位于不同的区域,物理地址实际上是不同的。比如,左边是连续的逻辑地址,右边是分离的,分成一块一块的物理地址空间。我们需要一个映射机制把逻辑地址空间映射到物理地址空间:
分段的管理机制可以用软件来实现,也可以用硬件。但软件实现的开销非常大,所以我们要考虑如何用硬件实现。
1、分段寻址方案
逻辑地址实际上是一维的,那我们如何把一维的逻辑地址跟物理地址对应?可以将一维的地址分成两部分,一部分是段寻址,一部分是段内偏移的寻址。具体来说有如下图的两种寻址方式。
X86使用的是段寄存器+地址寄存器实现方案。
下图表示了硬件实现方案:
从左上角开始看。当CPU在执行某条指令的时候,需要进行寻址(找数据,代码等),此时CPU得到的是一个逻辑地址。CPU将逻辑地址按照前半部分段号和后半部分偏移分开。
首先希望根据段号得到段所在物理内存的起始地址。这时候需要使用段表。
段表中存放了一个对应关系,那就是逻辑地址的段号和物理地址的对应关系。
另外,由于每个段的大小是不一样的。我们需要了解每个段的长度限制,这也要存在段表中。
段表有个索引,索引的每一项就是由段号决定的。
这样就可以根据段号,在段表中查到段对应的物理内存的起始地址,以及大小的限制。
找到之后,CPU比对这个大小限制和逻辑地址(通过Limit Register),看是否满足条件。如果不满足条件,就产生一个异常。
如果在合理区间之内,将起始地址和偏移量相加,得到一个实际的物理地址。
段表是操作系统在正式寻址之前建立好的。
2、分页寻址方案
分段机制现在用得比较少,绝大部分现代计算机都用的分页机制。
分页机制跟分段类似,也需要一个页号和页内偏移量。分页跟分段的一个最大区别是,页的大小是不变的。
步骤如下:
(1)帧(Frame)
物理地址=,
就表示帧的大小。
下面有个地址计算的实例
(2)页(Page)
计算方式跟前面是类似的。但因为这是逻辑地址,因此页号跟物理地址对应的帧号可能会不一样,但每一页的大小,以及页内偏移跟帧是一样的。
跟前面分段的方法一样,首先CPU得到逻辑地址,逻辑地址分成两块,一块表示页号,一块表示页内偏移地址。跟前面一样,有一个页表,页表的索引就是页号,内容是帧号。我们可以通过页