1.概述
传统存储管理方式具有两个特征
一次性
:作业必须一次性全部装入内存后,才能开始运行。驻留性
:作业被装入内存后,就一直驻留在内存中,在其运行期间作业的任何部分都无法被换出。
显然,这两个特性非常的糟糕,于是乎,我们提出了虚拟内存管理的架构设计。
虚拟存储器的最大容量由计算机的地址结构而定。
局部性原理
时间局部性
:程序中的某条指令一旦执行,不久后该指令可能将再次执行;程序中的某些数据被访问过,不久后该数据可能再次被访问。栗子🌰:循环。空间局部性
:一旦程序访问了某个存储单元,不久之后其周围的存储单元可能也会被访问到。栗子🌰:数组访问。
虚拟内存技术实际上建立了"内存-外存"两级存储器结构,利用局部性原理来实现高速缓存。
基于局部性原理,在程序装入时,仅将程序当前要运行的少数页面或段装入内存,其余的暂时放在外存。随着程序的执行,在执行过程中当访问的信息不在内存中时,便将所需要的部分由外存调入内存,而一些暂时用不到的内容则由内存换出到外存中,从而腾出一些空间存放调入内存的信息,这样系统给用户提供了一个看似比实际容量大得多的存储器,我们称之为虚拟存储器,但这种存储器实际上并不存在。
虚拟存储的实现需要建立在离散分配的内存管理方式上。
2.特征
2.1 多次性
作业装入时无需将整个程序一次性装入,而是按需装入,后续随运行的需要再将所需内容调入或换出即可。
2.2 对换性
作业运行时无需常驻内存,允许将那些程序暂时用不到的程序和数据部分从内存调出到外存的对换区。待以后需要时,再将其调入。
2.3 虚拟性
从逻辑上扩充内存的容量,使用户所看到的内存容量远远大于实际的存储容量。
离散性
也是虚拟内存的一个特征。
3.技术实现
3.1 请求分页管理方式
3.1.1 页表机制
与基本分页系统不同的是,它不要求作业一次性全部调入内存中,但它需要处理请求页面不在内存中的问题。
状态位
:指明该页面是否已调入内存。访问字段
:记录本页面被访问的次数或页面最近已有多久未被访问到。修改位
:指明该页面在调入内存后是否被修改过,以确定页面是否需要写回外存。外存地址
:指明该页面在外存上的物理地址。
3.1.2 缺页中断机构
- 当请求的页面不在内存中时,将产生一个缺页中断,这时OS将调入该页面到内存中,若此时内存已满,则按照一定的换出算法淘汰掉一个页面(若该页面已被修改过,则还要写回外存)以腾出空间供该页面调入。
- 缺页中断属于内部异常,因为这是在指令执行过程中产生的中断。
- 一条指令在执行过程中可能会产生多次缺页中断。
进程在执行过程中发生了缺页中断,经OS处理后,应继续执行被中断的那一条指令。
3.1.3 地址变换机构
基于基本分页系统的变换机构,增加了产生和处理缺页中断、换入换出页面的机构。
访问过程如下图:
4 页框分配
4.1 驻留集
给一个进程分配的物理页框的集合称为这个进程的驻留集。
驻留集的分配需要注意下面几点:
- 分配给一个进程的页框越少,驻留在内存中的进程数量就越多,从而可以提高CPU的利用率。
- 若分配给一个进程的页框越多,根据局部性原理,这对其缺页率影响不大。
- 若分配给一个进程的页框越少,根据局部性原理,其缺页率比较高。
4.2 内存分配策略
4.2.1 固定分配局部置换
为每个进程分配一定数目的物理块,在其运行过程中,根据情况进行适当地换入和换出。发生缺页中断需要调入新页面时,需要将其现有的页面之一换出,以保证分配给该进程的内存空间不变。
4.2.2 可变分配全局置换
为每个进程分配一定数目的物理块,在其运行过程中,根据情况进行适当地换入和换出。发生缺页中断需要调入新页面时,OS将从系统的空闲物理块队列中分配一个给该进程,然后将所缺页调入。
该方式可以动态地增加进程的物理块,但盲目给线程增加物理块可能会导致多道程序的并发能力下降。
4.2.3 可变分配局部置换
为每个进程分配一定数目的物理块,在其运行过程中,根据情况进行适当地换入和换出。发生缺页中断需要调入新页面时,OS将从该进程在内存中所占用的页面选择一个换出,然后再将所缺页换入。若进程频繁发生缺页中断,则OS将为该进程额外分配几个物理块,直至该进程的缺页率趋于平稳,若进程缺页率很低,则OS将适当减少分配给该进程的物理块数量。
该方式的实现更加复杂,页需要更大的开销,但能保证进程不仅不会过多地调页,还保证了系统的多道程序并发能力。
4.3 物理块调入算法
4.3.1 平均分配算法
将OS中所有可供分配的物理块平均分配给每个进程。
4.3.2 按比例分配算法
根据进程的大小按比例分配物理块。
4.3.3 优先权分配算法
为重要和紧迫的进程分配跟多的物理块。
4.4 调入页面的时机
4.4.1 预调入策略
根据局部性原理,调入页面的时候顺便将其周围的页调入会比一次只调入一个页更高效,但话又说回来,若周围的页在未来又可能不会被使用到,那这个方案此时又是低效的。因此该策略以预测为基础,对将日后会用到的周围的页进行调入。
这种策略主要用于进程的首次调入,并由开发人员指出应该调入哪些页。
4.4.2 请求调页策略
若进程在运行过程中所请求的页面不在内存中,将向OS提出请求,请求调入所缺页到内存中。该策略下调入的页将一定会被访问,该策略也易于实现。
该方式的缺点是每次只能调入一个页,这增加了磁盘I/O开销。
4.5 从何处调入页面
三种情况:
4.5.1 系统拥有足够多的对换区空间
从对换区调入所缺页以提高调页速度,因此,在进程运行前,需要将其所需的有关文件从文件区复制到对换区。
4.5.2 系统缺少足够多的对换区空间
凡是不会被修改的文件将从文件区直接调入,换出页面时,若页面未被修改则不必换出,若页面已被修改,则换出到对换区,后面需要时再从对换区换入。
4.5.3 UNIX方式
与进程有关的文件都存放在文件区,因此未运行过的页面将从文件区调入,曾经运行但又被换出的页面将被存放在对换区,待下次调入时将从对换区调入。若进程请求的共享页面已被其他进程调入内存,则无需再从对换区调入。
请求分页系统中,外存分为两部分:用于存放文件的文件区和用于存放对换页面的对换区。
文件区采用离散分配的方式,对换区采用连续分配的方式。
对换区的I/O速度比文件区要快。
4.6 调入页面的过程
5.页面置换算法
5.1 最佳(OPT)置换算法
该算法将选择以后永不使用的页面或者最长时间内不再被访问的页面进行淘汰。
由于人们无法预知哪个页面后续将不再使用,因此该算法无法实现。
5.2 先进先出(FIFO)置换算法
该算法将优先淘汰最早进入内存的页面。
只有该算法会出现
Belady
现象:进程被分配的物理块数增大,但缺页率不减反增的现象。OPT和LRU算法无Belady问题。
FIFO算法是基于队列实现的。
5.3 最近最少使用(LRU)置换算法
该算法将选择最近最长时间未被访问过的页面进行淘汰。
LRU算法与OPT算法的区别:LRU算法是向前看的,OPT算法是向后看的。
LRU算法是基于堆栈实现的。
LRU算法的性能很好(接近于OPT),但需要寄存器和栈的硬件支持。
LRU算法实现起来耗费高的原因是需要对所有的页进行排序,LRU算法需要对所有页最近被访问的时间进行记录,然后排序并查找访问时间最久的页进行置换,这会产生很大而定开销,为此,需要在页表项中增设LRU位。
5.4 时钟(CLOCK)置换算法
5.4.1 简单CLOCK置换算法
该算法规定,调入的页将组成一个循环队列,队列外还配备一个替换指针,其初始指向第一个位置,然后美调入一个页,其访问位被置为1,当腰要换出一个页时,该替换指针将从当前方向顺向循环扫描,若当前位置访问位为1,则将其置为0后继续向下扫描,若当前位置的访问位为0,则换出该位置的页,同时调入新页到此位置,置访问位为1,然后替换指针停止扫描,同时将指向调整为换出页面所在位置的下一个位置。
5.4.2 改进型CLOCK置换算法
在简单CLOCK置换算法的基础上,增加一个修改位。
其扫描过程的判别依据如下:
- 先扫描一圈
访问位 = 0,修改位 = 0
的页面,将遇到的第一个符合条件的页面换出,后续工作同前一个算法。(本次扫描期间不改变访问位) - 若前一步扫描无果,则进行第二次扫描,寻找
访问位 = 0,修改位 = 1
的页面,将遇到的第一个符合条件的页面换出,后续工作同前一个算法。(本次扫描期间将所有扫描过的访问位置为0) - 若第二步也扫描无果,则继续从第一步开始执行。
改进型CLOCK算法相对于简单CLOCK算法而言,其对页面状态做了进一步的细分,尽量优先换出未被访问的页面、未被修改过的页面。
改进型CLOCK算法能够减少磁盘的I/O次数,但为了换出一个页而循环扫描好几轮,这将导致开销有所增加。
6.抖动
刚刚换出的页面马上又要换入主存,刚刚换入的页面马上又要换出主存的现象称为抖动。
根本原因是系统中同时运行的进程数量太多,导致分配给每个进程的物理块数太少,进而使得进程在运行过程中出现频繁换页的现象。
前面的几种置换算法策略均可能出现抖动的情况。
产生内存抖动的原因主要是页面置换算法的不合理。
7.工作集
- 工作集是指在某段时间间隔内,进程要访问的页面集合。
- 工作集可由时间和工作集窗口大小来确定。
- 对于局部性良好的程序,其工作集要比工作窗口小很多。
- 工作集模型的原理:OS跟踪每个进程的工作集,然后分配大于工作集的物理块给每个进程。落在工作集的页面将调入到驻留集中,不在工作集的页面将从驻留集中调出。若有空闲物理块,便可再调入一个进程到内存,若所有进程的工作集超出了可用物理块数,则需要暂停一个现有进程,将其页面调出并将物理块分配给其他进程,以防止出现抖动现象。
对于上面这个栗子🌰:
工作窗口大小为5,t1时刻的工作集为{2,3,5}
,t2时刻的工作集为{1,2,3,4}
。
8.内存映射文件(Memory-Mapped Files)
它将磁盘文件的全部或部分内容与进程虚拟地址空间的某个区域建立映射关系,后续便可直接访问被映射的文件而不必执行文件I/O操作,也无需对文件内容进行缓存处理。
允许多个进程并发地内存映射同一个文件。
使用内存映射文件所进行的任何交互都是在内存中进行的,并且都是以标准的内存地址形式来访问的。
磁盘的周期性分页都是由OS在后台隐蔽实现的,对应用程序是透明的。
9.地址翻译
(请自行查阅王道书😊)