交换技术
- 为什么需要交换技术?
- 就是当我们内存不足以装载运行程序的时候, 或者剩余内存很小的时候, 怎么使得进程跑起来
内存扩充技术
- 内存紧缩技术
- 将碎片合并, 留出更多的空间给进程
覆盖技术
-
程序大小超过物理内存总和
-
过程很简单, 就是将不会冲突的部分共享一块内存, 运行一块覆盖一块(个人理解)
-
用户自己定义, 声明覆盖结构
-
没什么卵用, 还需要自己去定义顺序
-
交换技术
- 核心思想, 就是借助磁盘, 将内存中的一些不需要的东西暂时移动到外存(磁盘),以达到扩充的目的, 等需要的时候再从磁盘读回来
- 交换的内容: 运行时动态创建的(堆栈等)
- 交换区(swap): 可以理解为一块不需要经过文件系统管理的区域, 操作系统可以直接调用底层的读写操作使其更加高效的访问.
- 交换时机
- 长时间不用的进程
- 内存不够了
- 不能交换的进程: 等待I/O的进程
虚拟存储
- 先了解一下可以存储数据的位置: 寄存器, 高速缓存, 内存, 磁盘
虚拟存储技术
- 就是将程序分段调入内存(需要多少调多少), 调入工作由操作系统完成
- 虚拟地址空间: 分配进程的虚拟内存
- 虚拟地址: 虚拟内存中指令或数据的位置, 该数据可以被访问, 看上去是内存的一部分
- 虚存: 将内存和磁盘结合起来, 得到了一个很大的空间叫做虚存
- 虚存大小最大可以在n位计算机达到2^n的空间
- 地址保护
- 确保进程有独立地址空间
- 确保进程访问合法地址范围(防止越界)
- 确保进程访问的操作是合法的(权限管理)
虚拟页式存储管理
- 将虚拟技术和页存储方案结合
- 流程
- 进程运行前, 将页面装载进入内存, 装载(0/1)页
- 之后用多少装多少
- 如果内存空间满了,则使用一定的置换算法进行调整
- 调页方法
- 请求调页: 需要的时候再请求
- 预先调页: 预测需要哪一页 提前调好
- 总结
- 感觉就是本来你程序1M, 一页只有10K那么当你只有10K在内存的时候, 是给人的感觉就是全都在了, 产生虚拟的感觉。其实就是用CPU+磁盘换取昂贵的内存空间
页表及页表项设计
- 虚拟地址空间通过页表查到对应的物理地址, 其中页表由页表项组成
- 页表项的设计(具体可以找相关代码看下数据结构)
- 页框号: 内存块号, 物理页面号, 页帧号
- 有效位(驻留位, 中断位): 表示该页在内存还是在磁盘
- 修改位: 在页框中的内容是否被修改了(因为可能会写入磁盘)
- 访问位: 引用位(表示页面是否被访问过)
- 保护位: 读/写权限设置
- 页目录: 页表页由于在内存中不连续存放, 因此需要引入页表页的地址索引表, 这样的表叫做页目录
- 二级页表地址转化过程
- 进程上CPU, 从寄存器中取得页目录的指针
- 根据页目录找到对应的页表(页目录中的地址和页表中的偏移量决定)
- 也表中查询相关页面和页内偏移量结合最终找到物理地址
- 反转页表
- 主要解决进程内存地址空间占用过大问题, 所有进程共用一张表hash表
地址转化过程及TLB引入
- 实际上整个地址转化的过程简单来说就是CPU拿到进程的虚拟地址, 然后通过内存管理单元(MMU)去找到相对应的物理地址
- MMU的工作流程就是查目录->查页表->结合页面偏移量->物理地址这么一个过程
- 但是MMU会引发两次或以上的内存访问, CPU的访问和内存指令的速度差异很大,造成CPU资源浪费
- 程序局部性原理: 个人理解就是程序每次运行的时候都是部分在运行, 因此, 就引入了快表的概念, 个人理解就有点像加了一层缓存, 快表的命中率越高, 说明速度越快
- 快表
- 又叫高速缓存, 一种随机的存储型存储器, 除了连线寻址机制外, 还有接线逻辑,可以在一个周期内匹配所有数据
- 特点: 按内容并行查找
- 总结: 快表很容易理解, 就理解为一个小型的redis就行。
页错误
- 定义: 地址转化过程中硬件发生一些异常, 转入操作系统去处理
- 常见案例
- 所访问的虚拟页面不在内存, 需要从磁盘中读取, 因此叫做缺页异常
- 页面访问权限不对, 如读权限页面进行写操作, 用户去访问内核地址, 错误访问地址等
缺页异常
- 定义: 是页错误的一种, 又叫Page Fault
- 流程
- 操作系统执行缺页异常处理程序, 获取磁盘地址,将页面调入内存
- 如果内存中有足够的空间, 那么就分配一个页框, 将页表中响应页表项的有效位置为1,并且修改对应的页框号
- 内存中如果没有足够空闲页框, 则选择一个页框进行替换,被修改的页框需要写回磁盘, 并将相应的页表项的dirty位修改然后有效位修改为0
软件相关策略
- 驻留集
- 给每个进程分配多少页框, 个人理解就是页框的集合
- 分配策略
- 固定分配策略: 就是按照进程的类型,固定分配一定数量的页框号
- 可变分配策略: 按照缺页率进行调整, 缺页率大的话就多分配一些页框反之小。
- 置换策略
- 置换的页框一定是最不可能访问的那一批
- 页框锁定
- 如果没有锁定页框, 进程运行时间就不确定了
- 一些需要锁定的案例: 操作系统核心代码, 关键数据结构, I/O缓冲区
- 清楚策略
- 将进程的驻留集收回
- 目的就是始终保持一定数量的空闲页框
- 性能方面比置换会好很多, 想想也知道, 如果置换会
- 过程
- 分派一个进程定期去执行清除操作, 如果页面装入内存后被修改过需要保存到磁盘, 这样保证每个空闲页框是干净的
- 页缓冲技术(个人理解就是渐进式删除)
- 不丢弃置换出的页, 将其按照修改状态加入相关页链表中
- 被修改的页定期写入磁盘, 一次写多个而不是一次一个 减少I/O次数
- 如果页框没被覆盖, 则被置换的页仍然留在页框中, 一旦进程需要访问该页, 可以迅速将其加入驻留集(代价很小)
页面置换算法
-
又称页面淘汰算法
-
最佳页面置换算法
- 置换以后不太可能需要的页面
- 这个算法有点迷, 相当于需要知道进程的走向, 如果能把进程访问过的页面都记录下来找找规律还是有点可能的
- 该算法是一种衡量其他算法是否好的标准
-
先进先出算法
- 置换出在内存停留最久的页面,也就是最先进入内存的页面
-
第二次机会算法(SCR)
- 按照先进先出算法选择一个页框, 检查访问位, 如果没被访问, 就置换出去, 被访问了,则设置状态位为未被访问, 下一次周期如果还是未被访问就置换出去, 相当于给第二次机会
- 被修改状态位的页会被放在链表的末尾
-
时钟算法
- 将页框虚拟成一个环状, 每次指针下移找到状态为未被访问的页框进行置换,否则修改状态位
-
最近未使用页面置换算法
- 通过访问位R和修改位M 进行判断
- 启动一个进程 R M位修改为0
- R定期清0(复位)
- 选择优先级最小的页面置换出去
- 什么页面优先级最小? 访问位0, 修改位0< 访问位0, 修改位1< 访问位1, 修改位0<都是1的
- 时钟算法 也能结合该算法
-
最近最少使用算法(LRU)
- 按照时间来, 就是离当前访问时间隔的最久的那个页框被置换
- 该算法最接近OPT算法,效果是最好的
- 问题是开销大,需要给每个页框维护一个时间戳
-
最不经常使用算法(NRU)
- 访问次数最少的被置换, 其实就是维护了一个软件的计数器, 每次发生时钟中断的时计数器加R(访问位), 发生缺页异常的时候选择计数器最少的置换出去
-
老化算法
- 通过访问位的变化, 给每个页面维护了一套二进制表, 二进制表中每次会根据访问位右移, 最后替换的页面就是移动后最小的那个页面
-
BELADY现象
- 非常有意思的一个现象, 在FIFO算法中, 进程分配的页框越多, 缺页次数竟然更多了
-
工作集算法
- 抖动: 虚存中, 页面在内存与磁盘之间频繁的切换, 导致调度页面所需时间比进程实际运行时间还多, 导致系统效率急速下降, 这样的现象叫做抖动。
- 基本思想: 根据程序的局部性原理, 程序中总是会集中访问某一部分页面, 所以如果能够让系统提供的物理页面和频繁访问的页面数量一致, 那么将会大大减少缺页次数
- 工作集: 和驻留集差不多, 就是一个进程当前使用的页框集合, 但是工作集会实时调整。所以准确的说, 工作集就是在某个时间范围内的使用的页框集合。
- 具体做法
- 页表项中多一个字段去记录页面最后一次被访问的时间
- 设置一个时间值T
- 根据一个页面的访问时间是否落在"当前时间-T"的范围内去判断是否在工作集中, 个人理解就是一直保持一个时间窗口
- 具体实现
- 遍历所有页表项, 如果发现页表项的R位是1, 清零, 设置访问时间为当前时间
- 如果R位是0, 计算时间窗口(“当前时间-T”), 判断页表项是否在工作集之外
- 如果在之外: 则该页面被置换的页面
- 如果之内: 在时间窗口之内的话, 就记录所有被扫描页面的最后访问时间的最小值, 重复之前步骤
其他相关技术
-
内存映射文件
- 进程通过系统调用(mmap) 将文件映射到虚拟地址空间的一部分, 访问这个文件就像访问内从中的一个大数组, 而不是对文件进行读写.
- 其实就是和很多设计相似, 先把映射关系做好, 需要用的的时候再真正Load进入内存
- 等进程结束或者显示的接触关系时, 所有被修改的页面会写回文件
-
写时复制技术
- Linux里面使用fork创建子进程的时候, 其实和父进程是共享一块物理内存的, 当子进程需要对共享的物理内存进行修改时, 由于物理内存是只读的, 所以会和写时复制标志冲突引发缺页异常(Page Fault), 在物理内存中会创建一块私有的只能被子进程访问的内存块, 供子进程使用。
- 因为进程之间对内存数据修改的场景较少,而读的场景较多。所以这样也是能提升效率的(个人理解)
参考
[1] 操作系统原理