虚拟内存
传统存储管理问题:
- 一次性:必须全部将数据加载进内存才能够进行运行,作业很大就没法装入内存运行
- 驻留性:一旦装入内存就会一直驻留在内存,然而一个进程在某个时间段内可能只会使用部分的数据与指令。
基于原理:
- 时间局部性:某条指令执行,不久后这条指令可能再次执行
- 空间局部性:访问了某个单元,其附近的存储单元很可能被再次访问
虚拟内存就是将进程可能很快就需要用到的数据与指令放入内存,将暂时不会用到的放入外存。只有需要运行的时候将其换入内存。
虚拟内存的三个特性:
- 多次性:多次调入内存而非一次
- 兑换性:无需一直驻留内存,没用就换出去
- 虚拟性:逻辑上扩充了内存容量
实现虚拟内存一定要使用离散分配方式,不能使用连续分配。
需要增加的功能:1. 请求调页功能 2.页面置换功能
请求分页管理
页表结构
为了实现调页需要添加几个字段
- 状态位:是否调入内存
- 访问字段:最近访问了几次,提供换出算法考虑
- 修改为:最近是否修改
- 外存地址
缺页中断机制
每当需要访问页面不在内存时候,产生一个缺页中断,交由操作系统中断处理程序处理中断。
将缺页进程阻塞,调页完成之后再将其唤醒。
- 如果内存中有空闲块,为进程分配一个空闲块
- 如果内存没有空闲块,就需要利用算法选择一个块将其淘汰
置换算法
最佳置换算法OPT
每次淘汰的页面都将是以后永不使用或者是在最长时间内不被使用的页面。
可以保证缺页率达到最低。
但问题是这种算法在现实中不可能实现,只能作为参照。
FIFO先进先出置换算法
每次淘汰的是最早进入内存的页面。
实现方法:将调入内存的页面根据调入的先后顺序排成一个队列。需要换出选择队头即可。
问题:只有这个算法会产生belady异常。当为进程分配的物理块增多时候,缺页次数不减反增。
LRU最近最久未使用
每次淘汰最近最久没有使用的界面。
需要访问字段记录上次被访问以来所经历的时间
算法性能是最好的,最接近OPT,但是算法比较复杂,开销大。
CLOCK时钟置换算法/NRU最近未用算法
- 简单的clock
为每一个页面设置一个访问位,将所有内存页面通过链接指针成一个循环队列。当某个页面被访问时候,访问位为1.当需要淘汰一个页面只需要检查页的访问为。
如果是0就将其换出,如果是1,将其置位0,再继续扫描。
最多会进行两轮扫描。 - 改进的时钟算法
加入考虑是否近期修改过。如果修改过还需要换出到外存。
添加一个修改为表示状态。
第一轮:找到(0, 0)替换,本轮不修改任何标志位
第二轮:重新扫描找到第一个(0,1)进行替换,并且遇到访问位为1的置为0
第三轮:重新扫描,寻找第一个(0,0)的页面,不修改标志位
第四轮:寻找第一个(0,1)进行替换
最多进行四轮一定会找到替换页面。
替换顺序:(0,0)> (0,1)>(1,0)>(1,1)