Loading... # 虚拟内存 ## 硬件和控制结构 * 运行时访问地址动态转换为物理地址——一个进程可被换入或换出内存,在执行的不同时刻占据内存的不同区域 * 一个进程可以被划分为多个块(页或段),这些块不需要连续地位于内存中 * 在一个进程的执行过程中,该进程不需要所有的页或段在内存中 **常驻集(resident set)**:进程执行的任何时候都在内存的部分 所需地址不在内存中:发生缺页中断→OS阻塞进程(要想继续执行这个进程,OS必须把这个逻辑地址读入内存) * 发出磁盘I/O读请求 * 在这个过程中可以调度另一个进程 * 从磁盘读入所需的块后,产生一个I/O中断,原来被阻塞的进程置为就绪态 前面要产生中断效率较低,提高系统利用率的方法有: 1. 在内存中保留多个进程:只载入每个进程的部分,在任何时刻至少有一个处于就绪态 2. 进程可以比内存的全部空间还大 对于第二种方法,增加一个虚拟内存(通常在磁盘上) * 支持更有效的系统并发度 * 解除用户和进程之间没有必要的紧密约束 ### 局部性和虚拟内存 **局部性原理**:程序和数据访问的集簇倾向 基于局部性原理 在一个短时间片内,只需要一部分进程片段,可以猜测最近可能会访问的块,表明虚存方案可行 **系统抖动(thrashing)**:一个块正好在将要用到之前换出,OS不得不很快地取回它 ### 分页 每个进程有自己的页表,每个页表项(page table entry)包含与内存中的页框相对应的页框号 P位:所对应的页是否在内存中 M位:相应页的内容从上次装入内存到现在是否已改变 未改变时,则在需要换出该页(写入磁盘)时,无需用页框中的内容更新该页 ![image-20220508193807458.png](http://xherlock.top/usr/uploads/2022/05/3060864885.png) 分页的地址转换系统 ![image-20220508194353301.png](http://xherlock.top/usr/uploads/2022/05/2352536403.png) 页表太大时会占用太多主存,因此大多数页表存储在虚存中,部分页表存在主存中 **32位地址的两级页表方案** ![image-20220508195044449.png](http://xherlock.top/usr/uploads/2022/05/3282080249.png) 虚拟地址前10位检索根页表,中间10位检索用户页表项页 前面的页表缺点是:页表大小与虚拟地址空间大小成正比;故采用反向页表(inverted page table),将虚拟地址中的页号用一个简单的散列函数映射到为hash值,指向反向页表;这样页表的大小只与实存相关 **反向页表包括** * 页号:虚拟地址的页号 * 进程标志符 * 控制位 * 链指针 ![image-20220508200155372.png](http://xherlock.top/usr/uploads/2022/05/4198278492.png) 原则上每次虚存访问会导致2次物理内存访问:一次取页表项,一次取数据(内存访问时间加倍) 为克服这个问题,为页表项使用一个特殊的高速缓存称为TLB,包含有最近用过的页表项 **给一个虚拟地址后的步骤** 1. 检查TLB,命中则得到页框号并形成实地址;若未命中则用页号去检索进程的页表 2. 检查页是否在内存中,不在产生缺页错误;在,从页表中得到页框号并形成实地址,同时更新TLB(包含这个新页表项) ![image-20220508202801059.png](http://xherlock.top/usr/uploads/2022/05/1499030881.png) ![image-20220508202820526.png](http://xherlock.top/usr/uploads/2022/05/983469463.png) ![image-20220508203007173.png](http://xherlock.top/usr/uploads/2022/05/1981453355.png) **页尺寸/大小** * 页越小,内部碎片越少 * 页越小,每个进程需要的页数量越多,页表更大(对大程序来说,部分页表在虚存中而非内存中) ![image-20220508205838649.png](http://xherlock.top/usr/uploads/2022/05/566914729.png) **图a解释** 页尺寸小时,每个进程在内存中有较多的页,一段时间后内存中的页都包含有最近访问的部分,缺页率较低 页尺寸增加时,每页包含的单元和任何一个最近访问过的单元越来越远,局部性原理被削弱,缺页率开始增长 当页尺寸接近整个进程大小时,缺页率下降 **图b解释** 缺页率还取决于分配给一个进程的页框的数量,越多缺页率越低 ### 分段 段的大小不等且动态分配,内存访问以段号和偏移量的形式组成地址 优点: * 简化了对不断增长的数据结构的处理 * 允许程序独立地改变或重新编译 * 有助于进程间的共享 * 有助于保护 每个进程有自己的段表,每个段表包含段在内存中的**起始地址和段的长度**,也有存在位和修改位 ![image-20220508211044085.png](http://xherlock.top/usr/uploads/2022/05/1164094587.png) ![image-20220508211100747.png](http://xherlock.top/usr/uploads/2022/06/3791933450.png) ### 段页式 * 分页对程序员是透明的,消除了外部碎片 * 分段对程序员是可见的,具有分段的优点 * 段页式每段分为固定大小的页,每个进程有一个段表和多个页表,每个段有一个页表 ![image-20220508212109277.png](http://xherlock.top/usr/uploads/2022/05/4071133510.png) ![image-20220508212131747.png](http://xherlock.top/usr/uploads/2022/05/996719747.png) ## OS软件 ### 读取策略 读取策略决定某页何时取入内存,常用的方法是**请求分页式(demand paging)**和**预先分页式(prepaging)** 请求分页式:只有当访问到某页的一个单元时才将该页取入内存 预先分页式:读取的页并非缺页中断请求的页,利用了大多数辅存设备有寻道时间和合理的延迟的特性 ### 放置策略 放置策略决定一个进程块驻留在实存的什么位置 ### 置换策略 置换策略决定置换当前内存中的哪一页,目标是移出最近最不可能访问的页(预测将来行为) **页框锁定**(frame locking):一个页框被锁定时,当前保存在该页框中的页不能被置换 eg:OS内核、重要控制结构、I/O缓冲区 **基本算法** * OPT(optimal,最佳):选择置换下次访问距当前时间最长的那些页,导致的缺页中断最少,但要求OS必须知道将来发生的事,不可能实现 * LRU(least recently used,最近最少使用):置换内存中最长时间未被引用的页(也是最近最不可能访问到的页),难以实现,加了时间戳后开销很大 * FIFO(first in first out,先进先出):把分配给进程的页框视为一个循环缓冲区,并按循环方式移动页,只需要一个指针,实现简单,隐含逻辑是置换驻留在内存中时间最长的页(但通常推断错误,需要反复换入换出某些页) * Clock(时钟策略):为每个页框关联一个使用位(use bit)的附加位。当某页首次装入内存时,使用位置1;该页随后被访问时,使用位也会置1;当需要置换页时,第一个遇到的页框使用位为0的被置换;在搜寻置换的页过程中,每个使用位为1的被置为0 ![重点](http://xherlock.top/usr/uploads/2022/05/1242428493.png) (星号表示使用位为1) ![image-20220509111600796.png](http://xherlock.top/usr/uploads/2022/05/1101314155.png) 在时钟策略中考虑修改位(m),与使用位(u)一起有四种情况: * u=0,m=0 * u=1,m=0 * u=0,m=1 * u=1,m=1 修改算法为: 1. 从指针当前位置出发,扫描页框缓冲区,扫描过程中不对使用位做修改,选择遇到的第一个页框u=m=0的用于置换 2. 若第一步失败,重新扫描,查找u=0,m=1的页框,选择第一个遇到的用于置换 3. 若第二步失败,指针回到最初位置,,所有页框使用位置0,重复第一步 **页缓冲** 使用FIFO的置换算法时,FIFO存在的问题是置换一个被修改过的页,代价比置换未被修改的页的代价要大,因为前者需要写回辅存 故采用页缓冲:不丢弃置换出的页,而是分配到: * 空闲页链表:未被修改 * 修改页链表:已被修改 ### 驻留集管理 对于分页式虚存,准备执行时不需要也没必要把一个进程的所有页都读入内存,因此OS必须决定读取多少页,并分配相应的内存空间 * 固定分配策略:为一个进程分配固定数量的页框 * 可变分配策略:允许分配给一个进程的页框在该进程的生命周期中不断的发生变化 **置换范围** * 局部置换:仅在产生这次缺页的进程的驻留页中选择 * 全局置换:把内存中所有未被锁定的页都作为置换的候选页 **三种驻留集管理方案** * 固定分配+局部置换:事先确定分配给进程的总页框数,分配过少缺页率很高,分配过多内存中只能又很少的几个程序 * 可变分配+全局置换:最容易实现,被很多OS采用 * 可变分配+局部置换: ### 清除策略 清除策略用于确定何时将已修改的一页写回辅存 * 请求式清除:只有当一页被选择用于置换时才被写回辅存 * 预约式清除:将已修改的多页在需要它们所占据的页框之前成批写回辅存 ### 加载控制 * 决定驻留在内存中的进程数目 * 太少,所有进程都处于阻塞态的概率较大,用于时间增加 * 太多,导致系统抖动 <img src="http://xherlock.top/usr/uploads/2022/05/2699523174.png" alt="image-20220509150727926" style="zoom:50%;" style=""> 最后修改:2022 年 06 月 23 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,请随意赞赏