操作系统---内存管理(下) 分段存储 段页式存储 虚拟内存 请求分页管理方式
内存管理学习笔记 :
操作系统---内存管理(上) 概念 覆盖交换技术 连续分配管理方式
操作系统---内存管理(下) 分段存储 段页式存储 虚拟内存 请求分页管理方式
基本分段存储管理方式
分段 : 进程的地址空间会按照自身的逻辑关系划分为若干个段, 每个段都有一个段名, 每段从0开始编址
内存分配规则 : 以段为单位进行分配, 每个段在内存中占据连续空间, 但各段之间可以不相邻
分段系统的组成:
- 段号------ 段号的位数决定了每个进程最多可以分为几个段
- 段内地址------段内地址的位数决定了每个段的最大长度是多少
段表
程序分为多个段, 各个段离散地装入内存, 为了保证程序能正常运行, 就必须能从物理内存中找到各个逻辑段的存放位置. 为此, 需为每个进程建立一张段映射表, 简称 " 段表 " .
关于段表 :
- 每个段对应一个段表项, 记录着该段在内存中的起始位置 ( 基址 ) 和 段长
- 各个段表项的长度是相同的, 因此和页号一样, 段号是" 隐含 "的, 不占据存储空间
查找过程
分段和分页的对比
-
页是信息的物理单位, 分页的主要目的是为了实现离散分配, 提高内存利用率. 分页仅仅是系统管理上的需要, 完全是系统行为, 对用户是不可见的
-
段是信息的逻辑单位, 分段的主要目的是更好地满足用户需求. 一个段通常包含着一组属于一个逻辑模块的信息, 分段对用户是可见的, 用户编程时需要显式地给出段名
-
页的大小是固定且由系统决定, 段的长度却不固定, 决定于用户编写的程序
-
分页的用户进程地址空间是一维的, 分段的用户进程是二维的.
- 分段比分页更容易实现信息的共享和保护
段页式内存管理方式
分页, 分段管理的优缺点分析
优点 | 缺点 | |
---|---|---|
分页管理 | 内存空间利用率高. 不会产生外部碎片, 只有少量的内部碎片 | 不方便逻辑模块实现信息的共享与保护 |
分段管理 | 方便实现逻辑模块信息的共享与保护 | 如果段长过大, 为其分配很大的连续空间会很不方便, 并且段式管理会产生外部碎片 |
段页式管理的结构
先分段 , 再分页
段页式管理的逻辑地址结构 :
由段号, 页号, 页内偏移 组成
- 段号的位数决定了每个进程最多可以分为几个段
- 页号位数决定了每个段最大有多少页
- 页内偏移量决定了页面大小和内存块的大小
注意 :
"分段"对用户是可见的, 而将各段"分页"对用户是不可见的, 系统会根据段内地址自动划分页号和段内偏移量, 因此段页式管理的地址结构是"二维"的.
段表, 页表
每一个进程对应一个段表, 每一个段又对应一个页表, 因此一个进程可能对应多个页表.
查找过程
- 由逻辑地址得到段号, 页号, 页内偏移
- 段号与段表寄存器的段长度比较, 检查是否越界
- 由段表始址, 段号找到对应段表项 ---- ( 一次访存)
- 根据段表中记录的页表长度, 检查页号是否越界
- 由段表中的页表地址, 页号得到查询页表, 找到相应页表项 ---- ( 二次访存)
- 由页面存放的内存块号, 页内偏移得到最终的物理地址
- 访问目标单元 ---- ( 三次访存)
虚拟内存
传统存储管理方式的特征, 缺点
- 一次性 : 作业必须一次性全部装入内存才能开始运行
- 作业很大时, 无法装入导致大作业无法运行
- 大量作业要求运行时内存无法容纳所有作业, 导致多道程序并发度下降
- 驻留性 : 一旦作业被装入内存, 就会一直驻留在内存中, 直到作业运行结束, 这样会导致内存中驻留大量的, 暂时用不到的数据, 浪费内存资源
虚拟内存---基于局部性原理
-
在程序装入时, 将程序中很快会用到的部分装入内存, 暂时用不到的部分留在外存, 就可以让程序开始执行.
-
在程序执行过程中, 当所访问的信息不在内存时, 由操作系统负责将所需信息由外存调入内存, 然后继续执行程序.
-
内存空间不够时, 操作系统负责将内存中暂时用不到的信息换出到外存
-
在用户看来, 就有一个比实际内存大很多的内存, 这就叫虚拟内存
注意 :
虚拟内存的最大容量是由计算机的地址结构 ( CPU的寻址范围 ) 确定的, 虚拟内存的实际容量 = $ min( 内存容量 + 外存容量, CPU寻址范围) $
虚拟内存的实现 :
-
请求分页存储管理
-
请求分段存储管理
-
请求段页式存储管理
操作系统需要提供的功能 :
- 请求调页 ( 段 )
- 页面置换 ( 段置换 )
缺页时请求掉页不一定页面置换, 若还有可用的内存块, 就不用进行页面置换
请求分页管理方式
页表机制
缺页中断机构
在请求分页操作系统中, 每当要访问的页面不在内存时, 便产生一个缺页中断, 然后由操作系统的缺页中断处理程序处理中断
此时缺页的进程阻塞, 放入阻塞队列, 调页完成后再将其唤醒, 放回就绪队列
-
如果内存中有空闲块, 则为进程分配一个空闲块, 将所缺页面装入该块, 并修改页表中相应的页表项
-
如果内存中没有空闲块, 则由页面置换算法选择一个页面淘汰, 若该页面在内存期间被修改过, 则要将其写回外存, 未修改过的页面不用写回外存
缺页中断是因为当前执行的指令想要访问目标页面未调入内存而产生的, 因此属于内中断 :
页面置换算法
最佳置换算法OPT
每次选择淘汰的页面是以后永不使用或者在最长时间内不会使用的页面, 保证最低的缺页率 . 但是操作系统无法预判页面访问序列, 这种算法是无法实现的
先进先出置换算法 FIFO
每次淘汰的页面是最早进入内存的页面
实现 : 将调入内存的页面根据调入的先后顺序排成一个队列, 需要置换页面的时候选择队首的页面.
实现简单, 算法性能差, 不适应进程实际运行时的规律
最近最久未使用算法 LRU
当需要淘汰一个页面的时候, 选择现有页面中t值最大的, 即最近最久未使用的页面.
做题时的方法 : 需要淘汰页面时, 逆向检查此时在内存中的几个页面号, 最后一个出现的页号就是需要被淘汰的
LRU算法的特点 : 性能好, 但实现起来需要专门的硬件支持, 算法开销大
时钟置换算法 ( CLOCK ) / 最近未用算法 ( NRU )
他们是同一种算法.
简单的CLOCK算法的实现方法 :
简单的时钟置换算法仅考虑到了一个页面最近是否被访问过, 但是事实上, 如果被淘汰的页面没有被修改过, 就不需要执行I/O操作写回外存. 只有被淘汰的页面被修改过时, 才需要写回外存------因此, 除了考虑一个页面最近有没有被访问过之外, 操作系统还应该考虑页面有没有被修改过. 在其他条件都相同时, 应该优先淘汰没有修改过的页面, 避免I/O操作, 这就是改进型的时钟置换算法的思想.
利用 (访问位, 修改位) 的形式表示各页面状态
对应页面 | |
---|---|
第一轮 : 找第一个 (0, 0)的帧用于替换 ( 不修改标志位 ) | 最近没访问且没修改 |
第二轮 : 找第一个 (0, 1)的帧用于替换 ( 将所有扫描过的帧访问位设为0) | 最近没访问但修改过 |
第三轮 : 找第一个 (0, 0)的帧用于替换 ( 不修改标志位 ) | 最近访问过但没修改 |
第四轮 : 找第一个 (0, 1)的帧用于替换 | 最近访问过也修改过 |
特点 : 开销小, 性能也不错
页面分配策略
驻留集
请求分页存储管理器中给进程分配的物理块的集合. ( 系统给进程分配了n各物理块 ----的另一种表述 : 驻留集大小为n)
在采用虚拟存储技术的系统中, 驻留集的大小一般小于进程的总大小
- 如果驻留集太小, 会导致缺页频繁, 系统要花大量的时间来处理缺页, 实际用于进程推进的时间很少
- 如果驻留集太大, 会导致多道程序并发度下降, 资源利用率降低
几种分配策略
固定分配全局置换不存在, 因为进程物理块固定后不会再分配给别人
- 可变分配全局置换 : 只要缺页就给分配新物理块
- 可变分配局部置换 : 根据发生缺页的频率来动态地增加或减少进程的物理块
何时调入页面
-
预调页策略
-
请求调页策略
何处调入页面
文件区用于调入不会被修改的数据, 对换区用用于调入可能被修改的数据
抖动现象
工作集
- 一般来说 驻留集的大小不能小于工作集的大小, 否则进程运行过程中将频繁缺页.