03.内存管理
概述
-
内存空间的分配与回收
- 连续分配管理方式
- 单一连续分配
- 固定分区分配
- 动态分区分配
- 非连续分配管理方式
- 连续分配管理方式
-
内存空间的扩充
- 覆盖技术
- 交换技术
- 虚拟存储技术
-
地址转换
- 操作系统需要提供地址转换功能, 负责程序的逻辑地址与物理地址的转换
-
存储保护
- 设置上下限寄存器
- 重定位寄存器(基址寄存器)和界地址寄存器(限长寄存器)
覆盖与交换
覆盖技术
-
必须由程序员声明覆盖结构, 操作系统完成自动覆盖
-
缺点: 对用户不透明, 增加了用户编程负担
交换技术
-
内存空间紧张时, 系统将内存中某些进程暂时换出外存, 把外存中某些已具备运行条件的进程换入内存(进程在内存与磁盘间动态调度)
区别
-
覆盖是在同一个程序或进程中的
-
交换是在不同进程(或作业)之间的
连续分配管理方式
为用户进程分配的必须是一个连续的内存空间
单一连续分配
固定分区分配
-
操作系统需要建立一个数据结构——分区说明表, 来实现各个分区的分配与回收
-
优点: 实现简单, 无外部碎片
-
缺点:
- 当用户程序太大时, 可能所有的分区都不能满足需求, 此时不得不采用覆盖技术来解决, 但这又会降低性能
- 会产生内部碎片, 内存利用率低
动态分区分配
-
支持多道程序, 在进程装入内存时, 根据进程的大小动态地建立分区
-
无内部碎片, 有外部碎片, 可用 “紧凑” 技术解决
动态分区分配算法
-
首次适应算法
-
最佳适应算法
-
最坏适应算法
-
邻近适应算法
非连续分配管理方式
为用户进程分配的可以是一些分散的内存空间
基本分页存储管理
分页
-
将内存空间分为一个个大小相等的分区, 每个分区就是一个页框, 每个页框有一个编号, 即页框号, 页框号从0开始
页框 = 页帧 = 内存块 = 物理块 = 物理页面
-
将进程的逻辑地址空间分为与页框大小相等的一个个部分, 每个部分称为一个页或页面. 每个页面也有一个编号, 即页号, 页号也是从0开始
页表
-
页表一般是放在连续的内存块中的
地址的转换
-
逻辑地址为页号和页内偏移量的组合
- 如果页面大小为2kB, 用二进制数表示逻辑地址, 则末尾K位即为页内偏移量, 其余部分就是页号
基本地址变换机构
借助进程的页表将逻辑地址转换为物理地址
-
通常会在系统中设置一个页表寄存器(PTR), 存放页表在内存中的起始地址F和页表长度M. 进程未执行时, 页表的起始和页表长度放在进程控制块(PCB)中, 当进程被调度时, 操作系统内核会把它们放到页表寄存器中
具有块表的地址变化机构
-
块表 (TLB)
- 高速缓存, 用来存放最近访问的页表项的副本, 可以加速地址变化的速度
两级页表
-
各级页表的大小不能超过一个页面
-
访存次数增加
基本分段存储管理
与"分页"最大的区别在于离散分配时所分配地址空间的基本单位不同
分段
-
进程的地址空间: 按照程序自身的逻辑关系划分为若干个段, 每个段都有一个段名, 每段从0开始编程
-
内存分配规则: 以段为单位进行分配, 每个段在内存中占据连续空间, 但各段之间可以不相邻
-
分段系统的 逻辑地址结构 由 段号(段名) 和 段内地址(段内偏移量) 组成
段表
地址的转换
分页 vs 分段
-
分页对用户不可见, 分段对用户可见
-
分页的地址空间是一维的, 分段的地址空间是二维的
-
分段更容易实现信息的共享和保护 (纯代码 / 可重写代码可以共享)
-
都需要两次访存
段页式存储管理
分段 + 分页
段表 + 页表
地址的转换
虚拟存储
基本概念
传统存储管理方式
-
上述的管理方式均为传统的存储管理
-
一次性: 作业必须一次性全部装入内存后才能开始运行
-
驻留性: 一旦作业被装入内存, 就会一直驻留在内存中, 直至作业运行结束
-
问题
- 作业很大时, 不能全部装入内存, 导致大作业无法运行
- 当大量作业要求运行时, 由于内存无法容纳所有作业, 因此只有少量作业能运行, 导致多道程序并发度下降
虚拟内存
-
定义
-
特征
- 多次性: 无需在作业运行时一次性全部装入内存, 而是允许被分成多次调入内存
- 对换性: 在作业运行时无需一直常驻内存, 而是允许在作业运行过程中, 将作业换入换出
- 虚拟性: 从逻辑上扩充了内存的容量, 使用户看到的内存容量远大于实际的容量
-
虚拟内存的实现
-
请求分页存储管理
-
请求分段存储管理
-
请求段页式存储管理
-
-
操作系统提供
- 请求调页(段)功能
- 页面(段)置换功能
请求分页管理方式
页表机制
缺页中断机构
-
缺页中断是因为当前执行的指令想要访问的目标页面未调入内存而产生的, 因此属于内中断
地址变换机构
-
找到页表项时需要检查页面是否在内存中
-
若页面不在内存中, 需要请求调页
-
若内存空间不够, 还需换出页面
-
页面调入内存后, 需要修改相应页表项
页面置换算法
最佳置换算法 (OPT)
-
理想的
-
每次选择淘汰的页面将是以后用不使用, 或者在最长时间内不再被访问的页面
-
性能最好
先进先出置换算法 (FIFO)
-
每次选择淘汰的页面是最早进入内存的页面
-
Belady异常 : 当为进程分配的物理块数增大时, 缺页次数不减反增的异常现象
-
实现简单, 性能差
最近最久未使用置换算法 (LRU)
-
每次淘汰的页面是最近最久未使用的页面
-
实现方法: 赋予每个页面对应的页表项中, 用访问字段记录该页面自上次被访问以来所经历的时间t
-
性能好, 但实现困难, 开销大
时钟置换算法 (CLOCK)
-
最近未用算法 (NRU)
-
性能和开销较均衡
改进型的时钟置换算法
-
只有被淘汰的页面被修改过时, 才需要写回外存
-
在其他条件都相同时, 应优先淘汰没有修改过的页面, 避免I/O操作
-
淘汰优先级
- 最近没访问, 且没修改过
- 最近没访问, 但修改过的页面
- 最近访问过, 但没修改的页面
- 最近访问过, 且修改过的页面
页面分配策略
驻留集
-
请求分页存储管理中给进程分配的物理块的集合
页面分配 置换策略
-
固定分配: 操作系统为每个进程分配一组固定数目的物理块, 在进程运行期间不再改变, 驻留集大小不变
-
可变分配: 先为每个进程分配一定数目的物理块, 在进程运行期间, 可根据情况做适当的增加或减少, 驻留集大小可变
-
局部置换: 发生缺页时只能选进程自己的物理块进行置换
-
全局置换: 可以将操作系统保留的空闲物理块分配给缺页进程, 也可以将别的进程持有的物理块置换到外存, 再分配给缺页进程
-
固定分配局部置换
-
可变分配全局置换
-
可变分配局部置换
调入页面的时机
-
预调页策略
-
请求调页策略
从何处调页
-
系统拥有足够的对换区空间
-
系统缺少足够的对换区空间 (调出时看是否修改过)
-
UNIX方式 (调出时看是否使用过)
抖动(颠簸)现象
工作集
-
在某段时间间隔内, 进程实际访问页面的集合
内存映射文件
-
操作系统向上层程序员提供的功能 (系统调用)
- 方便程序员访问文件数据
- 方便多个进程共享同一个文件