590 likes | 834 Views
虚拟内存. 第六章(教材第五章 5.6 部分内容) 2006 年 12 月. 基本概念. 前面第五章所讨论的内存管理策略,都基于一个要求:执行指令必须在物理内存中,而满足这一要求的第一个方法是将 整个 进程放在内存中 覆盖和动态加载可以帮助减轻这种限制 虚拟内存 (VM) 这种技术允许执行的进程不完全在内存中 不容易实现 , 如果使用得不好可能影响效率. 基本概念. 实际程序检测结果表明, 大多数情况下,(程序运行时) 并非整个 程序都需要(在内存中)
E N D
虚拟内存 第六章(教材第五章5.6部分内容) 2006年12月
基本概念 • 前面第五章所讨论的内存管理策略,都基于一个要求:执行指令必须在物理内存中,而满足这一要求的第一个方法是将整个进程放在内存中 • 覆盖和动态加载可以帮助减轻这种限制 • 虚拟内存 (VM)这种技术允许执行的进程不完全在内存中 • 不容易实现, 如果使用得不好可能影响效率
基本概念 • 实际程序检测结果表明, 大多数情况下,(程序运行时)并非整个程序都需要(在内存中) • 用以处理常见错误情况的代码 ——这种错误很少发生(就是说,像这样的代码,由于错误很少发生,所以这种代码几乎不执行) • 即使整个程序都需要时, 也不大可能同时需要所有的程序 • 覆盖(就是说,由于不大可能同时需要,所以内存空间可以相互覆盖)
基本概念 • (让)运行的程序只有部分在内存中,这样的好处有: • 用户的程序不会受可用物理内存数量的限制 • 每个用户程序将使用更少的内存, 这样更多的程序可以同时运行,提高CPU的使用率
基本概念 • VM(虚拟内存)是一个需要硬件支持的技术 • 这个概念首先由Fotheringham于1961年设计提出的 • 在高速储存设备上实现 (如:disk硬盘) • 虚拟内存通常采用请求页面调度来实现 • 在支持 VM的系统中,覆盖技术消失了
请求页 • 请求页面调度系统类似于分页系统加上交换 • 交换技术 如下: • 初始时,进程驻留在次级存储器上 (磁盘) • 当需要执行进程时,将它换入内存。然后整个进程被调入内存中运行,即进程的每个页面被加载在内存的空闲帧中
请求页 • 页面交换技术使用的策略是只有当一个页面需要时才把它调入内存中 • 而交换则操纵整个进程(即进程一运行,就把所有页面都调入),换入换出以一个进程为单位,而页面交换技术只关心进程的单独一个页面(即只有一个页面需要时才调入) • 这样调页程序就避免了读入那些不使用的页,也减少了交换时间和所需的物理内存空间。
0 1 页0 2 页 0 3 页2 0 1 4 页1 1 4 页1 5 2 3 页2 6 3 7 7 页3 页3 8 9 分页 页表 逻辑 内存 物理 内存
页0 页1 页0 页2 页3 页4 2 页4 页1 3 页5 页6 5 页7 页6 7 页8 页9 页9 8 虚拟 存储 逻辑 内存 物理 内存 请求页
页错误(缺页) • 当进程试图访问那些尚未调入到内存的页时即需要的页面不在内存中时,将出现什么情况? • 可能需要从一个页面中读取一条指令,而该页面当前不在物理内存中,或者 • 一条指令需要读写一个页面中的某个位置,而该页面当前不在物理内存中 • 出现以上的任何一种情况, 内存管理(模块)产生一个页面错误
页错误 • 指令中止,然后产生一个缺页中断 • 该中断被操作系统中的服务例程截获,服务例程从虚拟内存中把页面加载到内存中 (必须找到一个空闲帧) • 产生中断的指令重新运行 • 页面被请求时才被加载, 因此称为“页面请求策略”
纯粹请求页面调度 • 纯粹请求页面调度: 只有在需要时才将页调入内存 • 一种极端情况是所有的页都不在内存中,这时就开始执行进程 • 当操作系统执行进程的第一条指令时,由于所在的页不在内存中,进程立即出现页错误 • 当页调入内存时,进程继续执行,并不断地出现页错误直到所需的页均在内存中
页替换 • 在某个时刻,一个进程可能引用一个当前不在内存的页,而此时物理内存也没有空闲帧可以分配给该请求页 • 操作系统可以结束这个进程 • 操作系统也可以将这个进程换出 • 更感兴趣的做法是:OS 用虚拟内存中的请求页替换现在内存中的某一页——如果不选择终止或换出这个进程的话
页替换 页替换过程需要处理的步骤 • 首先,查找所需页在磁盘上的位置 • 其次,查找一个空闲帧,如果有空闲帧就装入该页 • 如果没有空闲帧,那么就用页替换算法选择一个“牺牲”帧 • 将所需页读入空闲帧或者空闲帧 • 改变相应的页表和帧表 • 重启用户进程
页替换算法 • 选择一个不容易产生页错误的替换算法非常重要 • 通常情况下,我们总是希望选用最低页错误率的替换算法
页替换算法 • 可以这样来评估一个算法,针对特定内存引用串运行某个替换算法,并计算出各个算法页错误的数量 • 可以人工的生产内存引用串 • 为了确定发生页错误的次数,还需要知道可用帧的数量
内存引用串 • 例如,如果跟踪一个特定进程,那么可记录如下地址顺序 0722, 0050, 0121, 0212, 0012, 0310, 0019, 0421, 0289, 0302, 0076, 0365, 0196 • CPU访问数据的物理地址可能值是按照先 0722, 然后 0050, 再 0121, …… • 如果每页大小为100字节,那么这个地址顺序可以转变为如下的引用串 7 0 1 2 0 3 0 4 2 3 0 3 1
页替换算法FIFO:先进先出算法Optimal:最优页替换算法页替换算法FIFO:先进先出算法Optimal:最优页替换算法
FIFO替换算法 • FIFO是最简单的页替换算法 • 该算法为每个页记录着该页调入内存的时间 • FIFO 的思想是总是替换当前进程最早进入内存的页(最早时间的页) • 算法特点: • 该算法容易理解和实现 • 但是其性能并不总是很好
FIFO先进先出页替换算法 • 最早的页可能是经常被引用的页,当有请求页申请空闲帧时,最早的页就被替换出,可是在需要它的时候,最早页就必须立即被再次加载 • 可能导致(那些)使用频繁的页被不必要地替换出,容易产生抖动现象
FIFO先进先出页替换算法 引用串 7 0 1 2 0 3 0 4 2 3 0 3 1 7 7 7 2 2 2 4 4 4 0 0 0 0 0 3 3 3 2 2 2 1 1 1 1 0 0 0 3 3 3 11 个页错误 (初始有三个空闲帧)
Optimal最优页替换算法 • 最优页替换算法是所有算法中产生页错误率最低的 • 最优页替换算法替换那些在最长时间中不会被使用的页 • 但这就象CPU进程调度中使用的短作业优先调度策略——如何知道哪一页是最长时间中不会被使用的页? • 该算法难于实现,需要引用串的未来知识,所以主要作为比较研究
Optimal最优页替换算法 引用串 7 0 1 2 0 3 0 4 2 3 0 3 1 7 7 7 2 2 2 0 1 0 0 0 0 4 4 4 1 1 3 3 3 3 8 个页错误 (初始有三个空闲帧)
LRU算法思想 • LRU是最优替换算法的近似算法 • LRU (最近最少使用)使用离过去最近作为不远将来的近似(向前看) • LRU 认为如果一个页面最近没有被使用,那么就有这样的可能,在将来的某些时候它不会被使用
LRU算法思想 • 因此, LRU 认为应该替换那些最长时间没有使用的页(相当理解最近没有使用的页) • LRU算法实现需要大量硬件支持,它的问题是为帧确定一个排序序列,这个序列按页帧上次使用的时间来定义
LRU算法 引用串 7 0 1 2 0 3 0 4 2 3 0 3 1 7 7 7 2 2 4 4 4 0 0 0 0 0 0 0 0 3 3 3 1 1 3 3 2 2 2 1 10 个页错误, 错误数量小于 FIFO (初始有三个空闲帧)
Belady-异常现象 • 对有的页替换算法,页错误率可能会随着所分配帧数的增加而增加,这种令人难以置信的结果称为Belady现象。 • 原期望为进程增加内存会减少页错误率,改善其性能,但结果相反。 • 对LRU和OPT页替换算法都没有Belady现象,只有FIFO算法具有此现象。 • 下面给出FIFO页替换算法产生Belady现象的例子
LRU 近似算法 • 很少有计算机系统能提供足够的硬件来支持真正LRU页替换算法 • 许多系统都通过引用位方式提供一定的支持,近似LRU。 • 页表内的每项都关联着一个引用位 • 所有的引用位都初始为0 • 每当引用一个页时(无论对页进行读或写),相应页的引用位就被硬件置位(从0到1)
LRU 近似算法 • 之后通过检测引用位,能确定哪些页使用过而哪些页未使用过 • 但是,通过检测引用位不能确定页使用的顺序 • 所以需要更多的机制来确定那个页是最近最长时间没有使用的 • 这样导致了很多近似LRU算法的页替换算法
LRU 近似算法1 • LRU 近似算法1 -附加引用位算法 • 通过在规定时间间隔里记录引用位值,能获得额外页的替换顺序信息 • 每一个页保留一个字节记录最近引用位的信息
LRU 近似算法1 • 在规定时间间隔(如每100ms)内,将引用位逻辑右移(舍弃低位),并将当前引用位至于最高位 • 可以把引用字节的值转换为一个整数,然后利用这个数值的大小来确定LRU页 • 整数值越小,就说明这个页是最近更少使用的页,所以具有最小值的页就是LRU页即最近最少使用的页,可以被替换
0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 LRU 近似算法1 (每页一个字节) 128 192 96 48 24
0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 LRU 近似算法1 (第二个页) 128 192 96 176 88 88比24大,也说明了该页最近使用过,所以不能先替换
LRU 近似算法2 • LRU 近似算法2 -二次机会算法 • 很类似使用带引用位的FIFO替换算法 • 如果引用位被设置即改为1,那么该页就是最近使用的页 • 当要选择一个页时,检查其引用位,如果值为0,就直接替换,如果值为1就给该页第二次机会,即不换出。
LRU 近似算法2 • 算法继续往下搜索替换页,但要清除引用位的值从1变为0 (1 0) • 如果所有的页都被引用,即引用位值为1(引用位被设置),当扫描一次后,全部引用位都清0,结果二次机会替换算法就演变成了FIFO算法。
0 1 1 0 1 0 1 0 0 1 0 1 0 1 0 0 0 0 1 0 1 LRU 近似算法2
LRU 近似算法3 • LRU 近似算法3 -(增强型二次机会算法) • 使用引用位和修改位 11 最近使用过且修改过 10 最近使用过但没有修改过 01 最近没有使用但修改过 00 最近没有使用且也没有修改 • ’00’是替换的最佳页 • 接下去是’01’,但替换之前需要将页写到磁盘
帧分配 • 如何在各个进程之间分配一定的空闲内存? • 当系统中只有一个进程时 • 考虑一块 128 KB的内存, 帧大小为 1KB (因此共128 帧) • OS 可能占用 35K, 留下 93 帧给用户 • 在 纯页面请求算法中,所有的 93 帧将被初始化为“空闲”
帧分配 • 当一个用户进程运行时,它产生一系列页面错误 • 当所有页面都被用尽时, 一种页面替换算法将被使用 • 当内存中有两个或更多进程时 • 如果给一个进程分配太少的页面, 它就开始出现页面错误
帧分配 • 最简单的方法: 给每个进程同样数目的帧 • 使用按比例分配, 根据进程的大小而不同 • 分配将根据系统多程序的程度而改变 • 真实世界的解决办法还必须考虑到进程优先级或被共享的页面
全局 vs.局部替换 • 影响帧分配方式的另一个重要因素是页面替换 • 我们可以把页面替换算法分成两大类 • 全局替换:把所有的物理页面同等对待,用于替换 • 当进程访问的页面不在内存中时, 内存中将被替换的页面可能属于其他进程——一个进程可以从其他进程处取得帧
全局 vs.局部替换 • 全局替换算法的变种是优先级替换算法: 高优先级的进程可以从低优先级进程处获得帧, 但反之则不允许 • 局部替换 • 每个进程仅从其自己的分配帧中进行选择 • 内存中被替换的页面只属于该进程的