虚拟存储:在非连续存储内存分配的基础上,可以把一部分内容放到外存的做法
需求背景:
- 增长迅速的存储需求:程序规模的增长速度远远大于存储器容量的增长速度
- 理想的存储器:更大,更快,更便宜,非易失性,实际张的存储器是目前很难达到的
- 要把硬盘的空间也用上,让硬盘在os的操作之下扮演内存的作用,使得常用的进程放在内存上,不常用的放在硬盘上
那么,在计算机系统中内存不够用的解决办法是:
- 覆盖overlay:如果程序太大,超过了内存的容量,采用手动的覆盖技术只把需要的指令和数据保存在内存中
- 交换swapping:如果程序太多,超过了内存的容量,可以采用自动交换的技术,把暂时不能执行的程序送到外存中
- 虚拟存储:在有限容量的内存中,以页为单位自动装入更多更大的程序
覆盖技术
- 目标:在较小的可用内存中运行较大的程序,常用于多道程序系统,与分区存储管理配合使用
- 方法:依据程序逻辑结构,将程序划分为若干功能相对独立的模块;将不会同时执行的模块共享同一块内存区域,其中常用功能的代码和数据视为必要部分常驻内存中,而不常用功能则视为可选部分可放在其他程序模块中,指在需要用到时才装入内存
- 原理:因为不存在调用关系的模块不必同时装入内存,从而可以相互覆盖,即这些模块共用一个分区
- 缺点:这个操作是需要程序员来将大的程序划分为若干个小的模块,增加编程的复杂度;并且覆盖模块从外存装入内存,是以时间换空间
交换技术
- 目标:增加正在运行或需要运行的程序的内存,考虑的不是单个进程在所有内存空间都不够用的情况
- 方法:将暂时不运行的程序放到外存,所以换入换出的单位是整个进程
- 问题:
1)交换时间:内存不够时或者有不够的可能时才换出
2)交换区的大小:必须足够大以存放所有进程的内存映像的拷贝
3)程序换入时的重定位:因为换入换出后内存位置不一定相同,所以采用动态地址映射
虚拟存储
背景:
由于覆盖技术的编程技术难度大,而交换技术处理器开销又大,因此引出虚拟存储技术希望结合两者的优点,即像覆盖技术一样不是把程序的所有内容放到内存中,又像交换技术一样,能够实现进程在内存和外存之间的交换从而获得更多的空闲内存空间,结合覆盖技术的话,就是对进程的部分内容在内存和外存之间交换
局部性原理——虚存技术的可行性支撑
局部性原理是指程序在执行过程中的一个较短时间内所执行的指令地址和操作的操作数地址分别局限于一定的区域:
- 时间局部性:一条指令的一次执行和下次执行,一个数据的一次访问和下次访问都集中在一个较短的时间里
- 空间局部性:当前指令和邻近的几条指令,当前访问的数据和邻近的几个数据都集中在一个较小区域内
- 分支局部性:一条跳转指令的两次执行,很可能跳到相同的内存位置(如,循环
局部性原理的存在表明我们程序执行的指令,所访问的数据有很好集中特征,它们会集中在一个局部的区域中,这样的话,如果我们能够预测它局限的区域,就可以将这个常要被访问的区域放到内存中,程序的性能就不会有大幅度下降了,因此说局部性原理从虚拟技术得以实现的理论基础
局部性体现的编程举例
C语言中是按行优先来设置数组的(------>这样)方法1是按行访问的,每访问下一个跳到下一行即跳过1024个数字,4K只能放1024个数字(一个int32位,4byte),所有i每次都会换入换出,而第二种方法是按列访问的,满足局部性
虚拟存储基本概念
- 思路:将不常用的部分内存块暂存到外村中
- 原理:
1) 装入程序时:只将当前指令执行需要的部分页面或段装入内存中,既可以开始执行
2)在运行过程中,发现需要的指令或访问的数据尚未存在于内存中,即缺页/缺段,处理器就会通知os将相应的页面或段调入到内存,再继续执行
3)在调入需要的指令到内存中后,也会在合适时候将暂时不适用的页面或段调出保存到外存上(怎么判断哪些是不用的,就是所谓的置换算法 - 实现方法:虚拟页式存储,虚拟段式存储
- 特征:
1)不连续性:物理内存通过“非连续内存分配”是不连续的,同样分配到磁盘中的也可以不连续,虚拟内存空间不连续
2)大用户空间:提供给用户的虚拟内存可大于实际的物理内存
3)部分交换:虚拟存储只对部分虚拟地址空间进行调入调出 - 支持技术:
1)硬件:页式或段式存储中的地址转换机制,以及我们如何知道是在内存还是外存中
2)操作系统:决定换入换出内存外存中的哪些页面或段,
虚拟页式存储
大部分虚拟存储系统都采用虚拟页式存储管理技术,是在页式存储管理的基础上,增加请求调页和页面置换功能
- 思路:装入部分页面到内存 ——> 发现缺页,向系统发出缺页请求 ——>os处理缺页异常将相应页面调入内存使得程序继续执行
- 虚拟页式存储中的地址转换与页式存储的地址转换原理一样,就是在页表中加一项判断是否有对应的物理内存,如果没有就表示那一项还在外存中,缺页异常了,其中虚拟页式存储的页表表项如下图:其中访问位用于后面的页面置换算法,因为置换算法就是根据该页的访问情况来设计的;修改位的话,如果修改过了就需要写回外存,如果没有修改过,那么外存中有反正有那个页面的,要调出的话直接从内存中删掉好了
- 缺页异常的处理流程
- 有一个虚拟内存性能评估公式:
有效存储器访问时间effective memory access time(EAT)……要用再记 8
页面置换算法——局部页面置换,全局页面置换
-
定义:置换算法是当缺页异常发生,需调入新页面而内存已经满时,要去选择被置换的物理页面
-
目标:尽可能减少页面的调入调出次数,把未来不再访问或者短期内不访问的页面调出
-
因此对页面未来访问情况的预判是不同置换算法的本质区别
-
☆☆☆☆注意的一点是:不是所有的页面都可以参与置换这个过程的,有些页面必须一直在内存中,在页表中对应页号就会添加一个锁定标志位,称为页面锁定,被frame locking的页面有下面两类:
1)必须常驻内存的逻辑页面‘
2)要求响应速度的代码和数据 -
置换算法的评估方法:
1)模拟页面置换行为,记录产生缺页的次数
2)这个方法的前提是需要记录进程访问内存的页面轨迹
3)更少的缺页就是更好的性能
局部页面置换算法
- 置换页面的选择范围仅限于当前进程占用的物理页面内存
- 最优算法(理想化),
- 先进先出(太差),
- 最近最久未使用(总结过去来预测未来,依据局部性原理LRU),可以用链表或栈去实现!!!!!
- 时钟算法,LRU的近似,FIFO的改进,充分利用
access bit
,装入内存时就置为1,发生缺页了若访问位为1则减1,为0则被置换。 - 二次机会:clock算法的修改版,利用
access bit
和dirty bit
将只读的页最快替换出去 - 最不常用算法LFU,对每个页面维护一个计数器,当缺页发生时,选择访问次数最少的;与LRU注意区别,LRU是时间上的最久为访问,LFU是频率上的,访问次数最少的
全局页面置换算法
置换页面的选择范围是所有可换出的物理页面,不管是哪个进程的
- 思路:为进程分配可变数目的物理页面,在运行过程中动态地调整常驻集地大小
- 全局置换算法要解决的问题:进程在不同阶段地内存需求是变化的,分配给进程的内存页需要在不同阶段有所变化
- 过程:当发生一个缺页中断时,被置换的页面可以是在其他进程当中,隔俄国并发进程竞争地使用物理页面
- 实现方式:缺页率算法PFF来动态调整常驻集的大小
- 缺页率算法:
1)缺页率 = 缺页次数/内存访问次数 = 缺页平均时间间隔的倒数
如果PFF高,表明缺页多,就增加常驻集,反之亦然。
2)算法:
抖动问题thrashing
- 如果分配给一个进程的物理页面太少,不能包含整个工作集,那么进程将会造成很多的缺页中断,需要频繁地在内存与外存之间替换页面,从而使进程的运行速度变得很慢,这种状态就称为“抖动”。
- 产生抖动的原因:随着驻留内存的进程数目增加,分配给每个进程的物理页面数不断较少,缺页率就会不断上升,所以OS要选择一个适当的进程数目和进程需要的帧数,以便在并发水平和缺页率之间达到一个平衡。
- 工作集:一个进程当前正在使用的逻辑页面集合,可表示为W(t,▲),t是当前执行的时刻,▲称为工作集窗口,一个定长的页面访问时间窗口,W(t,▲)是当前时刻t前的▲时间窗口中所有访问页面所组成的集合,|W(t,▲)|指工作集大小,即页面数目