内存管理中的核心问题
- 存储分配:主要是讨论和解决躲到作业之间共享主存的存储空间的问题(虚拟地址空间),怎么为作业分配物理空间?
- 存储器资源的组织:区、段、页式。
- 地址转换:页表、段表逻辑地址与物理地址的转换。
- 虚拟存储调度问题:页面置换算法。
分区式存储管理
单道程序的内存分配 – 静态分配
对于单任务操作系统(内存中只有两个程序:一个用户程序、一个操作系统),由于操作系统所占空间是固定的,因此用户程序永远加载到同一个地址,并且可以在预先编译加载的时候计算出用户程序的地址。所以对于单道程序的内存管理就直接简单粗暴的加载上去就行,没有什么技巧。不再赘述。
多道程序的内存分配 – 动态分配
多道程序的内存分配采用分区式分配的方法。把内存分为一些大小相等或不等的分区,每个应用程序占用一个或几个分区,操作系统占用其中一个分区。具体实现中又分为:固定式分区和可变式分区。
- 固定式分区:分区大小可以不相同,但是一定是固定的,这就意味着需要程序去适配分区,即可能会出现内碎片(一个分区内有空白空间未使用)。具体分配方式上又有单一队列分配和多队列分配。
- 单一队列:所有程序都在同一个队列中等待分配,每次加载的时候,选择一个当前最大的分区进行加载。
- 多队列:由于程序大小和分区大小不一定匹配,有可能形成一个小程序占用一个大分区的情况,从而造成内存里虽然有小分区闲置但无法加载大程序的情况。这时,可以采用多个队列,给每个分区一个队列,程序按照大小排在相应的队列里。
- 可变式分区:分区边界可以移动,即分区大小可变。优点是没有内碎片,但是会出现外碎片。(这些外碎片,可以通过紧凑技术移动已分配的分区的地址空间,将零碎的空闲分区合成一个大的空闲分区,不过这个移动的开销较大)
空闲空间的管理
对于内存空间中空闲空间的管理方式,主要有两种:位图法、分区链表法。
- 位图法:给每个分配单元赋予一个字位,用来记录该分配单元是否闲置。例如,字位取值为0表示单元闲置,取值为1则表示已被占用。
- 空间成本固定、时间成本低、没有容错能力(除非设什么校验码的)
- 分区链表法:将内存空间单元以链表的形式顺序链接起来,每个结点需包含是否空闲、单元大小、单元的起始地址、下一个结点的指针等信息。
- 空间成本取决于程序数量、时间成本高、有一定容错能力(因为是占用空间和空闲空间相间分布的,所以一定程度上可以互相验证)。
可变分区分配算法
由于一个可变分区分配之后,内部未使用的空闲分区可以再划分出来成为新的空闲分区,所以可变分区的分配方法比固定分区复杂一点。总的来说,可变分区的分配方法有两大类:基于链表的顺序搜索的分配算法、基于索引的分配算法。首先,介绍基于链表的顺序搜索的分配算法。
- 首次适应算法(First Fit):每个空白区按其在存储空间中地址递增的顺序连在一起,在为作业分配存储区域时,从这个空白区域链的始端开始查找,选择第一个足以满足请求的空白块。
- 优先利用内存低地址部分的空闲分区。但由于低地址部分不断被划分,留下许多难以利用的很小的空闲分区(碎片或零头),而每次查找又都是从低地址部分开始,增加了查找可用空闲分区的开销。
- 下次适应算法(Next Fit):把存储空间中空白区构成一个循环链,每次为存储请求查找合适的分区时,总是从上次查找结束的地方开始,只要找到一个足够大的空白