内存管理:连续内存分配(固定分区、动态分区、伙伴系统)
内存保护
需要保护操作系统不受用户进程的影响,同时保护用户进程不受其他用户进程的影响。两种方法
-
CPU中设置上、下限寄存器。
存放用户作业在主存中的下限和上限地址,每当CPU要访问一个地址时,分别和两个寄存器的值对比,判断有无越界 - 采用 重定位寄存器(或基址寄存器) 和 界地址寄存器(限长寄存器) 来实现保护。
重定位寄存器中含最小的物理地址值,界地址寄存器含逻辑地址的最大值。
每个逻辑地址值必须小于界地址寄存器;若比较后未越界则加上重定位寄存器的值后映射成物理地址,再送内存单元。
覆盖(Overlay)
早期用的。
基本思想:由于程序运行时并非任何时候都要访问程序及数据的各个部分(尤其是大程序),因此可把用户空间分成一个固定区和若干覆盖区。将经常活跃的部分放在固定区,其他部分按调用关系分段。首先将那些即将要访问的段放入覆盖区,其他段放在外存中,在需要调用前,系统再将其调入覆盖区,替换覆盖区中原有的段。
实现:
- 将程序的必要部分代码和数据常驻内存;
- 可选部分在其他程序模块中实现,平时存放在外存中(覆盖文件),需
要用到时才装入到内存; - 不存在调用关系的模块不必同时装入到内存,可相互覆盖。
特点:打破了必须将一个进程全部信息装入主存后才能运行的限制;但当同时运行代码大于主存时仍不能运行;内存中能更新的地方只有覆盖区的段,不在覆盖区的段会常驻内存。
碎片整理:分区对换(Swapping)
早期使用,基本思想:
- 把内存中处于等待状态(或在CPU调度原则下被剥夺运行权力的)程序换出到外存上【换出】,以腾出足够的内存空间;
- 把准备好竞争CPU运行的程序从辅存移到内存【换入】。
优点:不要求用户给出程序段之间的逻辑覆盖结构。
注意:
- 交换需要备份存储,通常是快速磁盘;
- 进程执行时间要比交换时间长;
- 若换出经常,必须确保该进程完全处于空闲状态;
- 交换空间常作为磁盘的一整块,且独立于文件系统,因此使用很快;
- 交换在内存吃紧时启动,系统负荷降低就暂停。
固定分区分配
把内存分为大小相等或不等的固定分区,在每个分区中只装入一道程序。
分区分配算法:为进程分配某个空闲分区。
- 分区相等时,任选一个空闲分区;
- 分区不等时,根据空闲分区选择最佳任务或根据任务选择最佳空闲分区。
存储保护:界限寄存器
优点: 比单一连续分配方法,内存利用率提高了;可以支持多道程序,无外部碎片;实现简单。
缺点:
- 分区数目确定,限制了系统中活跃进程的数目
- 小作业的内部碎片可能比较大;
- 作业必须预先能估计要占用多大的内存空间。
动态分区分配
优点:
- 支持多道程序
- 管理方案相对简单,不需要更多的软、硬件开销
- 实现存储保护的手段比较简单
缺点:
- 主存利用不够充分,存在外部碎片; ➡ 通过紧凑技术解决
- 无法实现多进程共享存储器的信息;
- 无法实现主存的逻辑扩充,进程的地址空间受实际物理内存的限制。
伙伴系统(Buddy system)
综合静态划分技术和动态划分技术的优点。
分配: 进程申请大小为k的空间,系统分配一 2u 的空闲分区,其中,2u-1<k ≤ 2u
- 查找大小为 2i 的空闲分区,若找到则分配;
- 若未找到大小为 2i 的空闲分区,则查找大小为 2i+1 的空闲分区;若找到,则将该空闲分区划分为相等的两个分区(一对伙伴),其中的一个用于分配,另一个分区加入大小为 2i 的空闲分区链中;
- 若未找到 2i+1 的空闲分区,则需要查找大小为 2i+2 的空闲分区,若找到则需要进行两次划分。第一次将其分割为大小为 2i+1 的两个分区,一个用于分配,另一个加入到大小为 2i+1 的空闲分区链中;第二次将第一次用于分配的空闲分区分割为 2i 的两个分区,一个用于分配,另一个加入到大小为 2i 的空闲分区链中。
- 若仍未找到 2i+2 的空闲分区,则继续查找 2i+3 的空闲分区,以此类推。
回收: 释放一个大小为 2i 的分区时,算法:
- 若事先不存在 2i 的空闲分区,则保留该分区为一个独立的空闲分区;
- 若事先已存在 2i 的空闲分区时,则将其与伙伴分区合并为大小为为 2i+1 的空闲分区;
- 若事先已存在 2i+1 的空闲分区时,继续合并为 2i+2 的空闲分区,以此类推。
缺点:速度快,但内存利用率不高。