Lecture 12 虚拟存储
操作系统
操作系统也是程序
操作系统的两个目标:
- 提供用户与计算机之间的接口(方便)
- 管理资源(使资源得以有效利用)
多任务处理
当CPU中正在执行的任务需要等待IO时,CPU处于空闲状态。这是对CPU资源的浪费,因此需要将更多的任务装入到主存中,以使得等待期间可以执行其它任务。
而对多任务的分配、调度就需要操作系统来完成。
内存分配 step by step
上文中提到,为了避免CPU进入空闲状态,应该要让尽可能多的程序进入主存中等待执行。
因此,如何在主存中容纳更多的进程是十分重要的。
增大内存
(显然不合理,有以下几个弊端)
- 主存价格很贵
- 程序对存储器容量的需求增长很快,简单地增大内存永远跟不上需求增长的速度
交换
在磁盘中维护几个请求队列
- 中间队列(临时从主存中调出的进程)
- 长期队列(等待执行的进程)
当主存中无进程处于就绪状态时,调回一个进程至中间队列,然后从中间队列/长期队列中调入另一个进程。
(弊端)
- 交换本身就是一种I/O操作,速度很慢
分区
-
固定长度分区
将主存划分为一系列固定长度的分区,每次调入一个进程时选择可容纳的最小的可用进程。
这会浪费很多空间
-
变长分区
当进程调入主存时,分配的分区大小与进程大小一样。
随着程序的执行,这种方式会导致存储器出现非常多小块
解决这个问题的一个办法是紧缩,操作系统移动存储器中的进程时将所有空闲块放置在一起组成一个块。但这又有新的问题:
- 费时
- 每次移动指令所在的块会导致指令中嵌入的地址发生改变
为了解决第二个问题,引入逻辑地址的概念,指令中的地址都是逻辑地址,表示相对于程序起始单元的地址。cpu执行一个进程时将起始单元对应的物理地址加到逻辑地址上得到真正的地址。
分页
主存中的空白部分之所以会产生,是因为总是将一个程序连续存放在主存中,因此两个程序之间的较小空白部分无法容纳另一个进程时就会成为空白。
为了解决这个问题,一方面可以采用上述紧缩策略,但速度太慢。另一个方案就是将程序划分为较小的单独的页,此时就可以以页为单位,不连续地将程序存储在主存中。
同时为了屏蔽指令中的地址变化,仍然采用逻辑地址的方法。而且每个页的起始地址都不同,需要页表来维护。
虚拟内存
分页在一定程度上已经使多道程序设计系统真正有效了。但仍然存在可优化的地方。
首先,回顾一下分页带来了什么便利?
- 分页使得主存的空间得到尽可能充分的利用。
- 逻辑地址概念的引入使得程序实际运行的物理地址对程序员(编译器)透明。
还有什么可优化的地方?
- 根据程序访问的局部性原理,一定时间内一个进程需要访问的内容局限在一定范围内,即相当多的页处于空闲状态。
- 程序员编程的范围不够大,很多时候一个程序占的总空间很大,但一定时间内访问的仅是一小部分。可是主存的大小限制了程序所占总空间的增长。
解决方法:请求分页思想
- 仅将一个进程当前执行的页加载进主存中,其它空闲的页存储在磁盘里。
这种思想解决了上述问题,程序员可以在一个虚拟的地址空间中编码,并且主存容纳的进程数量也极大地增长。
虚拟存储器
“请求分页思想”本质上就是一种缓存思想,但其与cache又有一些细节上的不同:
- (主存-磁盘)的速度损失远大于(cache-主存),因此需要极高的命中率。
根据对cache性能的讨论,与命中率相关的几个因素:
- 关联度
- cache大小
- cache大小一定时,块大小
在这里,提高关联度可行, 因为主存很大,所以提高每页的大小也可行。(增大主存大小也可,但这不属于分配范畴)
cache容量十分有限,因此增大cache块的大小带来cache行数减少是显著的.而主存很大,增大页表的大小在很大范围内不会很显著地影响主存页项数,因此需要在一定范围内增大页
分页式
- 主存和虚存被划分为大小相等的页面(虚拟页、页框)
- 通过页表维护虚拟页、磁盘和页框的关系
页表
逻辑地址: 虚拟页号 + 页内偏移量
页表保存在主存中,包含以下信息:
装入位 | 修改位 | 使用位 | 存储权限 | 禁止缓存 | 存放位置 |
---|---|---|---|---|---|
0表示不在主存,1反之 | 是否修改过(回写控制位) | 页面使用情况(替换控制位) | 用于存储保护 | 用于保证数据一致性 | 装入位为1时,指向主存中的页框。装入位为0时,若指向磁盘则为未缓存页,若为null则为未分配页 |
查表得到物理地址: 物理页号 + 页内偏移量
页表中放入了所有虚拟页,因此每一页的顺序是固定的,即虚拟页号.因此不需要在页表项中保存页号
快表
页表位于主存中,每次转换地址都需要访问主存。继续应用缓存思想,可以将页表缓存到cache里,这就是快表
为了提高命中率同时提高速度,快表采用组相联/全相联+随机替换
虚拟存储访存过程
)
VA:虚拟地址, PA:物理地址
TLB中的所有页表项都是VALID项,因为只有被载入到主存的页表项才会加载进TLB中
分段式
将程序和数据分成不同长度的段,将所需的段加载到主存中。
虚拟地址:段号 + 段内偏移量