本文主要参考《计算机操作系统(第四版)》(西安电子科技大学出版社)以及清华大学操作系统公开课(向勇、陈渝),整理操作系统的基本概念,供自己复习查阅。
虚拟存储器
内存管理中涉及的方法均要求作业全部装入内存后才能开始工作,但内存容量总是有限的。为了解决这一问题,我们可以在物理上增加内存容量,但显然这会增加系统成本,并且受到机器自身限制;又或者,我们可以从操作系统层面入手,在逻辑上扩充内存容量,这也就是虚拟存储技术。
概述
在不采用虚存的系统中往往具有如下特征:
- 一次性,即作业必须一次性全部装入内存后才能开始运行。
- 驻留性,即从作业装入内存开始直到作业运行结束,整个作业都会一直驻留在内存中,任何部分都不会被换出。
- 局部性,即在较短的一段时间内,程序的执行只会局限在一个部分,所访问的存储空间也会局限在某个区域,即所谓的空间局部性。
定义
基于以上特征我们可以知道,程序运行之前没有必要全部装入内存,而在发现缺少当前要运行的部分后才发出中断请求(缺页中断、缺段中断),并将缺少部分调入内存再继续执行。由此也可以得出虚存的定义:虚拟存储器,是指能从逻辑上扩充内存容量并具有请求调入和置换功能的存储器系统。
特征
- 多次性,即相对于传统存储器系统而言,虚拟存储器系统允许作业被分成多次调入内存运行。
- 对换性,即允许作业在运行过程中换入换出,有效提高内存利用率。
- 虚拟性,即在逻辑上扩大内存容量,使用户所看到的内存容量远大于实际容量。
虚拟性是基于多次性和对换性的,而多次性和对换性又必须建立在离散分配的基础上。
实现
虚存的实现方式有两种,均需要软件和硬件支持:
- 请求分页系统,基于分页系统,增加了请求调页以及页面置换功能。
- 请求分段系统,基于分段系统,增加了请求调段以及分段置换功能。
请求分页存储管理方式
由于页面的大小固定,请求分页系统在实现上比请求分段系统简单,也是目前最常用的实现虚存的方式。
硬件支持
为了实现请求分页,系统需要有请求页表机制、缺页中断机构和地址变换机构。
请求页表机制
请求页表即在页表的基础上增设4个字段,即页表项内容为:页号、物理块号、状态位、访问字段、修改位、外存地址。新增字段的作用如下:
- 状态位:用于指示该页是否已被调入内存,供程序访问时参考。
- 访问字段:用于记录该页最近的访问次数或最近累计未被访问的时间,供置换算法选择换出页面时参考。
- 修改位:标识该页是否被修改过,供置换页面参考。(由于内存中的每一页在外存上都有一份副本,若该页在内存中未被修改,则置换时就无需写回外存。)
- 外存地址:用于指示该页在外存上的地址,供置换页面参考。
缺页中断机构
每当待访问页面不在内存时便产生一个缺页中断,请求系统把缺页调入内存。与一般中断相比,缺页中断比较特殊:
- 缺页中断在指令执行时产生和处理。一般中断是在指令执行后检查是否有中断产生,而缺页中断会在指令访问的也不存在时立即产生并得到处理。
- 一条指令执行期间可能产生多次缺页中断。
地址变换机构
请求分页系统的地址变换机构也是在分页系统的基础上拓展而得。
在进行地址变换时,首先检索快表,找到则修改表项的访问位,供后续置换参考,对于写指令,还须把修改位置“1”,最后利用页表项中的物理块号和页内地址形成物理地址;若未找到,则到内存中查找页表,找到后首先检查其状态位,确定该页是否调入内存,若未调入则产生缺页中断后请求调入内存,最后将该页写入快表。当快表满时,还应采取置换算法置换页。
页面置换算法
最佳(Optimal)置换算法
这是一种理论上的算法,其淘汰的页面是以后最长时间不使用的或永不使用的,但这也是无法预知的,因此该算法无法实现。最佳置换算法的作用是作为置换算法的标准,评判其他算法的优劣。
先进先出算法
顾名思义,该算法每次淘汰的是最早进入内存的页面。这个算法实现简单,只需把进驻页面排成一队列,并设置一替换指针指向最老的页面即可。但它与通常页面的使用规律不符,可能是性能最差的算法。
最近最久未使用(Least Recently Used,LRU)算法
LRU算法利用最近的过去预测最近的将来,即选择最近最久未使用的页面进行淘汰。这是一种较好的算法,但由于它需要了解进程在内存中的各个页面各有多少时间未被访问,且需要快速知道哪个页面是最近最久未使用的,故其需要较多的硬件支持。该算法可以用栈或移位寄存器实现。
用寄存器实现时,须为每个内存中的页面都配备一移位寄存器,当进程访问物理块时,将相应的移位寄存器最高位置“1”,而定时信号每隔一定时间把寄存器右移一位。若把寄存器看作一整数,则数值最小的页面即最近最久未使用的页面。
最少使用(Least Frequently Used,LFU)算法
最少使用算法选择最近使用最少的页面作为淘汰页。在实现上同样可以使用移位寄存器,实现方法与LRU类似,最近时间使用最少的页面即寄存器各位之和最小的页面。但在这种方法中,寄存器的一位记录的是一定时间间隔内该页的访问情况,并不能真实反应页面的使用情况。
Clock置换算法
虽然LRU是较好的算法,但其需要较多的硬件支持,故在实际应用中通常采用其近似算法——Clock置换算法。
简单型
相较于为每一页配置一移位寄存器,简单Clock置换算法只需为每一页设置一访问位,再把内存中的所有页面用链接指针串成一循环队列。当页面被访问时,将其访问位置“1”。在选择淘汰页面时只需检查访问位,若访问位为0则换出;若为1则留存,检查下一页面,直至找到为止。但由于访问位只有一位,故其只能表示该页是否被访问过,而淘汰时也是选择未使用的页面直接换出,也因此该算法又称为最近未用(Not Recently Used,NRU)算法。
改进型
改进型算法增加了一个因素——置换代价,这是因为在简单型算法中,被置换的页面很可能是被修改过的页面,这类页面置换时需要重新写回磁盘,代价较大。
设访问位为A,修改位为M,则页面可以分为4类:
- A=0,M=0,即最近未访问且未修改;
- A=0,M=1,即最近未访问但已被修改,淘汰需写回;
- A=1,M=0,即最近被访问但未被修改,可能再次访问;
- A=1,M=1,即最近被访问且被修改,很可能再次访问。
在进行置换时,首先遍历队列寻找第一类页面,找到则直接置换;未找到则再次遍历,寻找第二类页面,找到则直接替换,同时把遍历过程中扫描过的页面的访问位重置为0;若未找到,则再次重复上面的步骤(由于第二步已经把所有访问位置0,即此时队列中只有第一、二类页面),最终必能找到可淘汰页面。
显然,在最坏的情况下,算法须4次遍历队列,算法开销有所增加,但可以减少磁盘I/O次数。
抖动
当同时在系统中运行的进程太多时,分配给每一个进程的物理块太少,不能满足进程正常运行的基本要求,致使每个进程在运行时频繁出现缺页。显然,对磁盘的有效访问时间也随之急剧增加,每个进程的大部分时间都用于页面的换入换出。我们称此时进程处于抖动状态。
请求分段存储管理方式
与请求分页系统类似,请求分段系统是以分段系统为基础的虚拟存储器系统,同样需要一定的硬件和相应的软件支持。
请求分段机制
在请求段表中的表项有:段名、段长、段基址、存取方式、访问字段、修改位、存在位、增补位、外存始址。新增字段的作用如下:
- 存取方式:由于段是信息的逻辑单位,故可以设置该字段对段实施保护。
- 访问字段:用于记录该段的访问频繁程度,供置换页面的选择参考。
- 修改位:标明该段是否被修改过。
- 存在位:指示本段是否已被调入内存。
- 增补位:表示本段在运行过程中是否发生过动态增长。
- 外存始址:指示本段在外存中的起始地址,即起始盘块号。
缺段中断机构
由于段不是定长的,缺段中断的处理会比缺页中断的复杂。但类似地,缺段中断也是在指令执行过程中产生;一条指令执行过程中也可能产生多次中断。但由于段是信息的逻辑单位,即不可能发生一组信息被分割在两个不同的段中。
地址变换机构
该机构也是建立在分段系统地址变换机构的基础上。在变换时也会执行越界检查、分段保护处理、缺段中断处理。
分段的共享与保护
分段共享需要的数据结构为共享段表,所有的共享段在表中都有一表项,其中记录了段的基本信息,以及段的引用计数。