虚拟存储是想把一部分内存中的内容暂时存放到外存中,以提供更大的内存空间。
虚拟存储的目标:
1. 只把部分程序放到内存中,从而运行比物理内存大的程序。并且由操作系统完成,无需程序员的干涉。
2. 实现进程在内存和外存在之间交换,从而获得更多的空闲内存空间。在内存与外存之间只交换进程的部分内容。
局部性原理:
具体讲虚拟存储之前先了解一下局部性原理。局部性原理是指程序在执行过程中的一个较短时期,所执行的指令地址和指令的操作数地址,分别局限于一定区域。比如通常指令在代码段,操作数在数据段。具体体现在以下几个方面:
- 时间局部性。一条指令的一次执行和下次执行,一个数据的一次访问与下次访问都集中在一个较短时期内;
- 空间局部性。当前指令和邻近的几条指令,当前访问的数据和邻近的几条数据都集中在一个较小的区域内;
- 分支局部性。一条跳转指令的两次执行,很可能跳转到相同的内存位置。
由于局部性原理的存在,从理论上讲,虚拟存储技术是能够实现的,可以取得满意的效果。
虚拟存储基本概念:
1. 思路:将不常用的部分内存块暂存到外存。
2. 原理:装载程序时,只将当前指令执行需要的部分页面或段装入内存;指令执行中需要的指令或数据不在内存中(缺页或缺段)时,处理器通知操作系统将相应的页或段调入内存中;操作系统将内存中暂时不用的页面或段保存到外存中,如何判定哪些不常用,需要后续的置换算法。
3. 实现方式:虚拟页式存储、虚拟段式存储。
虚拟存储的基本特征:
1. 不连续性。物理内存分配非连续,虚拟地址空间使用非连续。
2. 大用户空间。提供给用户的虚拟内存可大于实际的物理内存。
3. 部分交换。虚拟存储支队部分虚拟地址空间进行调入和调出。
虚拟存储的支撑技术:
- 硬件支持。页式或短时存储中的地址转换机制。除之前非连续内存管理中所讲的地址转换,还要增加判断所需要的内容不再内存中。
- 操作系统支持。管理内存和外存间页面或段的换入和换出。
虚拟页式存储:
在页式存储管理的基础上,增加请求调页和页面置换。具体思路是当用户程序要装载到内存运行时,只装入部分页面就启动程序运行。进程在运行中发现有需要的代码或数据不在内存时,则向系统发出缺页异常请求。操作系统在处理缺页异常时,将外存中相应的页面调入内存,使得进程能够继续运行。如下图所示,在页表中加入标志位,当发现缺页时触发缺页异常,操作系统接管,找到相应页面置入内存,并将标志位修改为有效。
虚拟页式管理中,页表项结构有相应调整,如下图:增加了几个标志位。其中驻留位用来表示是否在内存中;修改位表示在内存中的该页是否被修改过,因为如果没有修改过而外存中又有这一页面时不需要置换,直接作废该页表项即可,如果被修改过则需要重新置换;访问位表示该页是否被访问过(读或写),用于置换算法,用于近似统计是否经常访问;保护位表示该页的允许访问方式,如可读可写。
示例:
下面是X86 32位系统以4K为页帧大小时的页表项结构:帧号项占20位,标志位中除了前面提到的驻留位、可写标志、访问位、修改位,还有几个没提到过的。一个是用户态标志,表示用户态是否可以访问;保留位,用于扩展,比如现在很多32位系统不仅支持4G内存;CD位,缓存是否有效,是否允许启用高速缓存;WT是否写通。
缺页异常:
缺页异常即发现需要的内存页不在内存中。却也异常处理流程如下图:即执行命令时CPU给出需要的逻辑地址,查找页表;发现缺页,产生缺页异常;操作系统启用缺页异常例程,查找页面在外存中的位置;从物理内存中找空闲页帧并将页面换入空闲处;将页表项修改为有效;重新执行导致异常的指令。可以看到这是最顺利的情况,如果换入时发现没有空闲页帧的话则需要额外几步:根据页面置换算法选择要被换出的页帧;判断该页帧是否被修改过,如果被修改过则写回外存,否则直接作废;将其对应的页表项改为无效;然后将需要的页帧换入空出来的区域,后续与最开始的流程一致。
虚拟页式存储中的外存是如何管理的呢?首先是在何处保存未被映射的页?因为必须能够方便地找到在外存中的页面内容,因此我们需要一个交换空间,有两种方式实现:磁盘或文件。Linux就是直接有交换分区。或者文件采用特殊格式存储未被映射的页面。
虚拟页式存储中的外存选择也是个问题。代码段本身就是存储在可执行文件中的,因此代码段是直接指向你的可执行文件;动态加载的共享库程序段也直接指向相应的文件;其他段放在对换区。
虚拟页式存储管理的性能如何评价呢?我们定义了一个有效存储访问时间(effective memory access time)EAT。
"访存时间" *(1-p)+缺页异常处理时间*缺页率p
举个例子:可以看到想要效率较高,需要缺页率p极小。