资源
第八讲 虚拟内存概念
-
为什么需要虚拟内存:计算机系统时常出现内存空间不够用的情况,虚拟存储可以在有限容量的内存中,以页为单位自动装入更多更大的程序。
-
解决内存空间不够用的三种技术:覆盖、交换和虚拟内存。
-
覆盖
- 目标:在较小的可用内存中运行较大的程序
- 方法:依据程序逻辑结构,将程序划分为若干功能相对独立的模块;将不会同时执行的模块共享同一块内存区域
- 必要部分(常用功能)的代码和数据常驻内存
- 可选部分(不常用功能)放在其他程序模块中,只在需要用到时装入内存
- 不存在调用关系的模块可相互覆盖,共用同一块内存区域
-
交换
- 目标:增加正在运行或需要运行的程序的内存
- 方法:可将暂时不能运行的程序放到外存。
- 换入换出的基本单位是整个进程的地址空间
- 程序换入时的重定位:采用动态地址映射的方法,程序换出后再换入时不需要放在原处
-
局部性原理
- 时间局部性:一条指令的一次执行和下次执行,一个数据的一次访问和下次访问都集中在一个较短时期内
- 空间局部性:当前指令和邻近的几条指令,当前访问的数据和邻近的几个数据都集中在一个较小区域内
- 分支局部性:一条跳转指令的两次执行,很可能跳到相同的内存位置。
- 局部性原理的意义:从理论上来说,虚拟存储技术是能够实现的,而且可取得满意的效果
- 利用局部性原理提高程序性能:比如按行遍历数组
-
虚拟存储的目标
- 只把部分程序放到内存中,从而运行比物理内存大的程序。由操作系统自动完成,无需程序员的干涉。
- 实现进程在内存与外存之间的交换,从而获得更多的空闲内存空间。在内存和外存之间只交换进程的部分内容。
-
虚拟存储的原理
- 装载程序时,只将当前指令执行需要的部分页面或段装入内存
- 指令执行中需要的指令或数据不在内存(称为缺页或缺段)时,处理器通知操作系统将相应的页面或段调入内存
- 操作系统将内存中暂时不用的页面或段保存到外存
- 从技术上来看,硬件提供页式或短时存储中的地址转换机制,操作系统管理内存和外存间页面或段的换入和换出
-
虚拟存储的基本特征
- 不连续性:物理内存分配非连续、虚拟地址空间使用非连续
- 大用户空间: 提供给用户的虚拟内存可大于实际的物理内存
- 部分交换: 虚拟存储只对部分虚拟地址空间进行调入和调出
-
虚拟页式存储管理:在页式存储管理的基础上,增加请求调页和页面置换
- 当用户程序要装载到内存运行时,只装入部分页面,就启动程序运行
- 进程在运行中发现有需要的代码或数据不在内存时,则向系统发出缺页异常请求
- 操作系统在处理缺页异常时,将外存中相应的页面调入内存,使得进程能继续运行
-
虚拟页式存储管理中的页表项结构
- 驻留位:表示该页是否在内存。1表示该页位于内存中,该页表项是有效的,可以使用;0表示该页当前在外存中,访问该页表项将导致缺页异常
- 修改位:表示在内存中的该页是否被修改过。回收该物理页面时,据此判断是否要把它的内容写回外存。
- 访问位:表示该页面是否被访问过(读或写)。用于页面置换算法。
- 保护位:表示该页的允许访问方式。只读、可读写、可执行等。
-
缺页异常的处理过程
- A. 在内存中有空闲物理页面时,分配一物理页帧f,转第E步
- B. 依据页面置换算法选择将被替换的物理页帧f,对应逻辑页q
- C. 如q被修改过,则把它写回外存
- D. 修改q的页表项中驻留位置为0
- E. 将需要访问的页p装入到物理页面f
- F. 修改p的页表项驻留位为1,物理页帧号为f
- G. 重新执行产生缺页的指令
-
虚拟页式存储中的外存管理
- 在何处保存未被映射的页?为了能方便地找到在外存中的页面内容,一般放在交换空间(磁盘或者文件),采用特殊格式存储未被映射的页面
- 虚拟页式存储中的外存选择
- 代码段:可执行二进制文件
- 动态加载的共享库程序段:动态调用的库文件
- 其它段:交换空间
-
虚拟页式存储性能度量:有效存储访问时间(effective memory access time, EAT)
- EAT = t0 - (1 - p) + t1 - p - (1 + q)
- 缺页率p
- 页修改概率q
- 访存时间t0
- 缺页异常处理时间t1(或者叫磁盘访问时间)
第九讲 页面置换算法
-
页面置换算法的功能:当出现缺页异常,需调入新页面而内存已满时,页面置换算法选择被置换出去的物理页面。
-
页面置换算法的目标:尽可能减少页面的调入调出次数、把未来不再访问或近期不再访问的页面调出。
-
页面锁定(frame locking):部分逻辑页面需要常驻内存,比如操作系统的关键部分、要求响应速度的代码和数据。这时使用页面中的锁定标志(lock bit)来实现。
-
页面置换算法的分类
- 局部页面置换算法:各进程的物理页面数已经确定,置换页面的范围仅限于当前进程占用的物理页面中。比如最优算法、先进先出算法、最近最久未被引用算法、时钟算法、最不常用算法。
- 全局页面置换算法:各进程的物理页面数动态变化,置换页面的范围是所有可换出的物理页面。比如工作集算法、缺页率算法。
- 局部页面置换算法没有考虑进程访存差异,比如有些进程再增加几个物理页面可能就大大降低缺页率,有些进程增加物理页面可能对缺页率影响不大
-
最优算法(OPT,Optimal):将未来最迟访问的页面换出。理想情形,无法实现。用于确定最少换入换出次数,以此为参照物考量其他算法的优劣。
-
先进先出算法(FIFO):将在内存中驻留时间最长的页面换出。记录每个物理页面换入内存的时间,将时间最小的页面换出。
-
最近最久未被引用算法(LRU):将最长时间没有被引用的页面换出。实现方法:记录每个物理页面最后一次被访问的时间,将时间最小的页面换出。
-
时钟置换算法(Clock):LRU和FIFO的折中,将访问位为0的页面换出。实现方法:时针首先指向第一个换入内存的页面,时针顺时针旋转,检查每次指向的页面,若页面访问位为0,则将其换出,并旋转时针到下一个页面;若页面访问位为1,则将其访问位清零,并旋转时针到下一个页面继续考察。为了避免换出被修改过的页面的时间开销,检查时可以跳过被修改过的页面。
-
最不常用算法(LFU):将访问次数最少的页面换出。实现方法:记录每个物理页面的访问次数,将访问次数最小的物理页面换出。如果多个物理页面的访问次数均为最小次数,则在其中选择换入内存时间最早的页面换出。
-
Belady现象
- 现象:采用FIFO等算法时,可能出现分配的物理页面数增加,缺页次数反而增加的异常现象。
- 原因:FIFO算法的置换特征与进程访问内存的动态特征矛盾,导致被它置换出去的页面不一定是进程近期不会访问的页面
- 什么算法或什么情况下会出现Belady现象?
- 可能出现Belady现象的算法:FIFU,Clock
- 不会出现Belady现象的算法:OPT、LRU。只要是使用栈的算法(每次换出栈底的页面),都不会出现Belady现象。
-
FIFO vs LRU vs Clock
- FIFO和LRU本质上都是先进先出的思路。FIFO根据页面进入内存的时间排序,LRU根据页面的最近访问时间排序
- FIFO的页面进入内存的顺序是不变的,而LRU需要动态调整页面的顺序
- LRU可退化成FIFO:当页面进入内存后就不再被访问,比如从头到尾看一遍视频
- FIFO开销小,但性能差,而且可能出现Belady现象
- LRU性能好,但开销大
- Clock是对FIFO和LRU的折中:页面访问时,不动态调整页面在链表的顺序,仅做标记;缺页时,再将它移到链表末尾。
- 对于未被访问的页面,Clock的性能和LRU一样好;对于已被访问的页面,Clock的性能差于LRU,但强于FIFO,因为它没有准确记录访问顺序,而只记录了页面是否被访问。
-
全局页面置换算法要解决的问题:进程在不同阶段的内存需求量是变化的,分配给进程的内存也需要在不同阶段有变化,全局页面置换算法需要确认分配给进程的物理页面数。
-
CPU利用率与并发进程数存在相互促进和制约的关系
- 进程数目少时,增加并发进程数目可提高CPU利用率
- 并发进程会导致内存访问增加
- 并发进程的内存访问会降低了访存的局部性特征
- 局部性特征的下降会导致缺页率的上升和CPU利用率的下降
-
工作集:一个进程当前正在使用的逻辑页面集合,可表示为二元函数W(t, delta)
- t是当前的执行时刻
- delta称为工作集窗口,即一个定长的页面访问时间窗口
- W(t, delta)表示当前时间t前的delta时间窗口中的所有访问页面所组成的集合
- 工作集算法:根据进程工作集的特征,在不同阶段给进程分配不同的内存
-
常驻集:在当前时刻,进程实际驻留在内存当中的页面集合。缺页率与常驻集的关系:
- 工作集包含在常驻集中时,缺页较小
- 工作集发生剧烈变动(过渡)时,缺页较多
- 当进程常驻集数目达到一定数目后,缺页率也不会明显下降
-
工作集的实现方法
- 思路:换出不在工作集的页面
- 窗口大小:当前时刻前的t个内存访问的页引用是工作集,t称为窗口大小
- 访存链表:维护窗口内的访存页面链表
- 访存时,换出不在工作集的页面,更新访存链表
- 缺页时,换入页面,更新访存链表
-
缺页率:缺页次数/内存访问次数。一般使用缺页平均时间间隔的倒数来近似。影响缺页率的因素:
- 页面置换算法
- 分配给进程的物理页面数目
- 页面大小
- 程序编写方法
-
缺页率置换算法(PFF, Page-Fault-Frequency)
- 通过调节常驻集大小,使每个进程的缺页率控制在一定范围内。具体而言,若进程缺页率过高,则增加常驻集以分配更多物理页面数;若进程缺页率过低,则减少常驻集以减少它的物理页面数
- 访存时,设置引用页标志
- 缺页时,计算从上次缺页时间t_last到当前时间t_cur的时间间隔,若t_cur - t_last > T,则置换所有[t_last, t_cur]时间内没被引用的物理页;若t_cur - t_last <= T,则增加缺失页到常驻集中。
- 缺页率算法相对工作集算法的开销要小:缺页率算法只在缺页中断中进行换页操作,而工作集算法在每次访存时都可能进行换页操作。
-
抖动问题
- 随着驻留内存的进程数目增多,每个进程的物理页面太少,不能包含工作集,造成大量缺页,频繁置换,导致进程运行速度变慢。
- 操作系统需要在并发水平和缺页率之间达到一个平衡
-
负载控制
- 通过调节并发进程数(MPL)来进行系统负载控制
- sum(WSi) = 内存大小
- 负载平衡点:平均缺页间隔时间(MTBF)= 缺页异常处理时间(PFST)
第十讲 实验三 虚拟内存管理
-
内存地址虚拟化能有效隔离不同进程的内存访问空间:在有了分页机制后,程序员或CPU“看到”的地址已经不是实际的物理地址了,这已经有一层虚拟化,我们可简称为内存地址虚拟化。有了内存地址虚拟化,我们就可以通过设置页表项来限定软件运行时的访问空间,确保软件运行不越界,完成内存访问保护的功能。
-
内存地址虚拟化能提供更大的内存“空间”:
- 按需分页:通过内存地址虚拟化,可以使得软件在没有访问某虚拟内存地址时不分配具体的物理内存,而只有在实际访问某虚拟内存地址时,操作系统再动态地分配物理内存,建立虚拟内存到物理内存的页映射关系,这种技术称为按需分页(demand paging) 。
- 页换入换出:把不经常访问的数据所占的内存空间临时写到硬盘上,这样可以腾出更多的空闲内存空间给经常访问的数据;当CPU访问到不经常访问的数据时,再把这些数据从硬盘读入到内存中,这种技术称为页换入换出(page swap in/out) 。这种内存管理技术给了程序员更大的内存“空间”,从而可以让更多的程序在内存中并发运行。
-
页访问异常(Page Fault)
- 在程序的执行过程中由于某种原因(页框不存在/写只读页等) 而使 CPU 无法最终访问到相应的物理内存单元,即无法完成从虚拟地址到物理地址映射时,CPU 会产生一次页访问异常,从而需要进行相应的页访问异常的中断服务例程。这个页访问异常处理的时机被操作系统充分利用来完成虚存管理,即实现“按需调页”/“页换入换出”处理的执行时机。当相关处理完成后,页访问异常服务例程会返回到产生异常的指令处重新执行,使得应用软件可以继续正常运行下去。
- 具体而言,当启动分页机制以后,如果一条指令或数据的虚拟地址所对应的物理页框不在内存中或者访问的类型有错误(比如写一个只读页或用户态程序访问内核态的数据等) ,就会发生页访问异常。产生页访问异常的原因主要有:
- 目标页帧不存在(页表项全为0,即该线性地址与物理地址尚未建立映射或者已经撤销)
- 相应的物理页帧不在内存中(页表项非空,但Present标志位=0,比如在swap分区或磁盘文件上)
- 不满足访问权限(此时页表项P标志=1,但低权限的程序试图访问高权限的地址空间,或者有程序试图写只读页面)
- CPU会把产生异常的线性地址存储在CR2中,并且把表示页访问异常类型的值(简称页访问异常错误码,errorCode)保存在中断栈中。页访问异常错误码有32位。位0为1表示对应物理页不存在;位1为1表示写异常(比如写了只读页);位2为1表示访问权限异常(比如用户态程序访问内核空间的数据)
- CR2是页故障线性地址寄存器,保存最后一次出现页故障的全32位线性地址。CR2用于发生页异常时报告出错信息。当发生页异常时,处理器把引起页异常的线性地址保存在CR2中。操作系统中对应的中断服务例程可以检查CR2的内容,从而查出线性地址空间中的哪个页引起本次异常。