一:内存的基本知识
1:内存的分层体系
- CPU微处理器(CPU寄存器+L1、L2高速缓存):速度快,容量小
- 主存、物理内存:速度稍快,容量大。主要用于放置操作系统和代码。
- 磁盘(虚拟内存):速度慢,容量最大用于扩充空间和备份数据
2:操作系统与内存
(1)操作系统的作用:
- 抽象:把物理地址抽象为逻辑地址
- 保护:每个进制都有独立的地址空间
- 共享:进程间通过访问相同的内存,传递数据
- 虚拟化:扩充地址空间
(2)操作系统的管理方法
- 程序重定位
- 分段
- 分页
- 虚拟内存
- 按需分与虚拟内存
(3)负责管理的硬件
MMU:内存管理单元,负责处理CPU的内存访问请求。
3:地址空间
(1)定义
- 物理地址空间:支持硬件的地址空间(内存条,主存),主存中真正的地址
- 逻辑地址空间:应用程序运行时所拥有的内存范围,从0号单元开始编址,顺序分配符号名对应的地址单元,并不是真正的地址
(2)地址生成
逻辑地址的生成:通过编译、汇编、链接、载入等方式生成应用程序所需要的逻辑地址空间。
物理地址的生成:通过逻辑地址的映射生成应用程序所需要的物理地址
- 逻辑地址的请求:ALU发出请求,需要逻辑地址的内容
- 查找映射关系:MMU通过映射关系,将逻辑地址映射为对应的物理地址。如果查找不到,再去内存查找
- 物理地址的请求:CPU通过总线向主存发出请求,需要物理地址的内容
- 主存通过总线传送物理地址内存的内容
(3)地址重定位
将逻辑地址映射为物理地址的过程
静止重定位:在程序装入主存时完成映射,不再变化
- 无需硬件地址变换机构的支持,只要求程序是可重定位的
- 必须给作业分配连续的存储区域
- 不能扩充存储空间
- 不能移动作业
- 多个作业难以共享同个程序的副本和数据
动态重定位:在程序运行期间完成映射
- 硬件地址变换机构的支持
- 程序可以换入换出主存,扩大主存空间
- 作业可以移动
- 可以利用较小的主存块
- 可以实现共享
(4)地址检查
- 基址/限长寄存器保护
- 检查逻辑地址空间的长度(界限寄存器)
- 加上逻辑地址空间的起始地址(基址寄存器),得到物理地址
- 上下界寄存器保护
- 检查逻辑地址空间的起始地址(上界寄存器)
- 检查逻辑地址空间的结束地址(下界寄存器)
二:内存的分配
1:连续分配——分区
(1)分配的问题
内存碎片:无法利用的空闲内存空间
- 外碎片:分配单元间的碎片
- 内碎片:已分配单元内的碎片
(2)分配的时机
- 在内存中加载应用程序
- 应用程序运行中需要访问数据
(3)分配方式
1:固定分区
在系统生成时将主存划分好多个分区,分区的大小可以不同,通过主存分配情况表管理主存
- 易产生内碎片:程序或作业的大小不可能与分区相同
2:可变分区
在作业装入主存时动态划分存储空间,通过已分配主存表和未分配主存表管理
分配算法
1: 首次适配:第一匹配分配
- 首次适应算法:从最低地址开始,使用可用的并且容量比需求大的第一个空闲块。
- 循环首次适应算法:从刚分配的空白区开始,使用可用的并且容量比需求大的第一个空闲块。
- 按地址排序空闲块
- 寻找合适空闲块并分配
- 回收时检查能否合并相邻的空闲块
优点
- 简单
- 易于产生更大的空闲块(在地址空间结尾)
缺点
- 易于产生外碎片
- 不确定性
2: 最优适配:最合适匹配分配
为了避免分割大空闲块,同时最小化外碎片,使用可用的并且容量比需求大的最小空闲块。
- 按尺寸排序空闲块
- 寻找合适空闲块并分配
- 回收时检查能否合并相邻的空闲块
优点
- 较简单
- 不会拆分大尺寸的空闲块,如果大部分需求都是小尺寸的则非常有效
缺点
- 易于产生外碎片
- 重分配慢
- 易产生没有用的微小碎片
3:最差适配:最不合适匹配分配
为了方便分割大空闲块,同时避免微小碎片,使用可用的并且容量比需求大的最大空闲块。
- 按尺寸排序空闲块
- 直接分配最大空闲块
- 回收时检查能否合并相邻的空闲块
优点
- 如果大部分需求都是大尺寸的则非常有效
缺点
- 易于产生外碎片
- 重分配慢
- 无法分配较大分区
3:可重定位式分区
移动所有已分配的分区成为连续区域,可以解决碎片问题
(4)碎片整理方法
压缩式碎片整理
重置程序以合并碎片(要求所有程序动态可重置)
- 重置时机:程序正在等待,没有执行
交换式碎片整理
抢占等待的程序并且回收他们的内存,此时等待的程序放在虚拟内存也就是磁盘中。
2:非连续分配——分页/段
(1)连续分配的问题
- 分配给一个程序的物理内存是连续的
- 内存利用率较低
- 会产生碎片问题
(2)非连续分配的优点
- 更好的利用、管理内存
- 支持共享代码与数据
- 支持动态加载,动态链接
(3) 分页机制
分页基础:
划分物理内存至固定大小的帧,同时划分逻辑地址空间至大小相同的页。帧是非连续的,页是连续的。不是所有的页都有对应的帧,因为可能在虚拟内存中。
地址结构
物理寻址:一个内存物理地址包含帧号和帧内偏移
- 帧号:F位(帧的数量2F)
- 帧内偏移:O位(帧的大小为2O字节)
- 物理地址:总共有F+O位,具体地址 = 帧号f × 2O + 帧内偏移量o
逻辑寻址:页的偏移量和帧的偏移量相同,但是页的大小不一定和帧的大小相同。
- 页号:P位(页的数量为2P)
- 帧内偏移:O位(页的大小为2O字节)
- 虚拟地址:总共有P+O位,具体地址 = 页号p × 2O + 帧内偏移量o
地址变换机构:页表寄存器(页表的始址和长度)
- CPU将逻辑地址分为页号+页内偏移量
- 如果页号不在页表长度寄存器的范围内,则越界中断
- 通过页表基址寄存器(PTBR)获取起始地址,从页表查找页号对应的帧号。
- 找到帧号,根据标志位判断物理帧是否存在
- 如果不存在,缺页中断
- 如果存在,加上之前的偏移量,得到对应的物理地址。
特点:
- 对用户是透明的
- 不易共享
- 页表空间可能过大
- 需要2次内存访问
改进:
时间上:使用快表,可能只需访问1次内存
快表(TLB):位于CPU内部的联想存储器,缓存近期经常访问的页帧转换表项,使用键值对表示页-帧的映射关系。
- CPU先直接查询快表,找出对应帧
- 如果查询失败,再查询页表。
- 如果在页表查询成功,再将其放入TLB缓存。
空间上:使用多级页表和反向页表,防止页面不存在而占有空间
多级页表:对页表分页,每个页表和内存的帧大小相同,分成多级后存入不同的帧,前一级记录下一级页表的起始地址,最后一级记录对应帧号。通过把页号分为K部分,形成多级间接页表,也就是具有K层页表树
- CPU先查询一级页表。从页表基址寄存器(PTBR)开始,根据页号的第一部分,查到对应下一级页表的起始地址。
- 从下一级页表的起始地址开始,根据页号的第二部分,查到对应的帧号
- 根据帧号和偏移量获取物理地址
反向页表:由于逻辑地址空间增长速度快于物理地址空间,前向映射页表变得繁琐。使用反向页表,表的大小和逻辑地址无关,并且相对于物理内存很小。
- 基于页寄存器:根据帧号查询页号,但是无法根据页号有效访问帧号
- 基于关联内存:如果帧数较少,可以把页寄存器放置在关联内存中,并行查找页号和帧号,但是内存开销过大。
- 基于哈希查找: 哈希表根据当前运行程序的PID和页号,运行哈希函数,得到对应页寄存器,从而获取帧号。但是可能会出现哈希冲突
(4) 分段机制
分段的基础:
- 程序由子程序和各种库等各种段组成。
- 数据由堆段,栈段和共享数据等各种段组成。
分段:更好的分离和共享
程序的地址空间是连续的逻辑地址空间,被划分为若干段,对应于内存的不同段,便于分离和共享程序各部分。每个段都是从0开始的连续地址空间,各段的长度是不等的
地址结构
物理寻址:一个内存物理地址包含帧号和帧内偏移
- 段号:S位(段的数量2S)
- 段内偏移:O位(段大小为2O字节)
- 物理地址:总共有S+O位,具体地址 = 段号s× 2O + 帧内偏移量o
地址变换机构:段表寄存器(段表的始址和长度)
程序逻辑地址空间与物理地址空间的映射分为两部分:段寻址+段偏移寻址
- 段寄存器+地址寄存器实现
- 单地址实现
- CPU将逻辑地址分为段号+段内偏移量
- 如果段号不在段表长度寄存器的范围内,则越界中断
- 通过段表基址寄存器获取起始地址,从段表查找段号对应的物理块号。
- 找到物理块号,根据标志位判断物理块是否存在
- 如果不存在,缺段中断
- 如果存在,加上之前的偏移量,得到对应的物理地址。
特点
- 易于共享
- 无法充分利用主存
(5) 段页式机制
将主存划分为等大的存储块,将用户程序按逻辑关系划分为若干段,再将段划分为若干页,以存储块为单位离散分配内存
地址变换机构:段表寄存器(页表起始地址+页表长度)
- 通过段号查找段表,获取页表的起始地址
- 通过页号和起始地址查找页表,获取物理块号
- 通过物理块号和偏移量获取物理地址
三:虚拟内存
(1)内存不够用的解决方法
- 手动覆盖技术:只把需要的指令和数据保存在内存中
- 自动交换技术:把暂时不需要的程序送入外存
- 自动虚拟存储技术:把暂时不需要的部分程序送入外存
(2)覆盖技术(程序内部)
定义:
在比较小的可用内存中运行较大的程序,与分区存储管理技术配合使用。
过程:
- 将程序按照自身逻辑功能划分为独立的模块和分区。
- 必要部分的代码和数据属于常驻区,常驻内存,负责调用其他程序
- 可选部分的代码和数据属于覆盖区,不会同时执行(即相互之间不会相互调用),在需要时装入内存。他们共享一块内存区域,按时间顺序运行,即相互覆盖
优点:
能够运行比当前空闲块还要大的程序
缺点:
- 增加了编程复杂度
- 时间换空间
(3)交换技术(程序与程序之间)
定义
多道程序在内存中,让正在运行的程序或需要运行的程序获得更多的内存资源。
过程
- 对于暂时不需要运行的程序,把整个地址空间的内容保存在外存中,从而获得空闲块空间。
- 外存中的某个程序需要运行时,把它的地址空间读入内存中。
优点:
能够获得更多的空闲内存空间
缺点:
- 对操作系统的性能有一定影响
- 需要较大的交换区,能够存放所有用户进程的内存映像拷贝
- 可能需要进行动态地址映射
(4)虚拟内存管理技术
虚拟存储器:具有请求调入和置换功能的,能在主存仅装入作业的一部分便可运行作业的存储器系统。逻辑容量由主存和外存容量之和和CPU可寻址的范围决定
特点:
- 和覆盖技术一样能够实现把程序的一部分内容放入内存,并且只需由操作系统来自动完成
- 和交互技术一样能够实现程序在内存和外存之间交换,并且只是交换一部分。
- 基于程序的局部性原理:
时间局部性:指令的一次执行和下一次执行,数据的一次访问和下一次访问都集中在一个较短时期内。
空间局部性:当前以及邻近的指令和数据都集中在一个较小的区域内
过程:
- 在装入程序时,只装入需要执行的部分页面或部分段,程序就可以执行
- 在程序运行过程中,如果产生缺页或缺段,则由CPU通知系统调把相应页或段调入内存,再继续执行程序。
- 在没有内存空间的情况下,操作系统把不需要用到的页面或段调出外存
优点:
- 用户空间很大
- 部分交换
- 空间不连续
实现
- 请求分页系统
- 请求分段系统
- 请求段页式系统
1. 硬件基础:
后备存储:一个虚拟地址空间的页面可以被映射在二级存储中的文件的某个位置。
存储形式:
- 数据:使用数据文件保存
- 代码段:使用可执行二进制文件保存
- 动态加载的程序段:使用动态调用的库文件
- 分区:使用特殊的交换区存储
页表中增加若干项字段
- 状态位
- 驻留位:表示该页是否在内存中
- 保护位:表示页的类型(只读,读写,可执行)
- 修改位:表示页是否被写过(如果写过,需要把新的数据写回外存中)
- 访问位:表示页是否被访问过
- 锁定位:表示必须常驻内存的页
- 辅存地址
- 访问字段
地址变换机构增加了产生和处理缺页中断、置换页等功能
2. 过程
- 调入内存:当一个用户程序需要运行时只装入部分页面
- 缺页中断:当需要的页面不在内存中时会发生缺页中断,请求调页
- 页面置换:系统将外存的页面调入内存
3. 缺页中断(驻留位=0):
状态位:
过程:
- 如果在内存中有空闲的物理页面,则不需要置换页面,直接分配一个物理页帧f,转向第4步
- 采用置换算法,选择一个被置换的页帧f,它对应的逻辑页为Q,如果该页被修改过,则需要写回外存。
- 对Q所对应的页表项进行修改,驻留位=0
- 将需要访问的页P装入到物理页帧f中
- 修改P对应的页表项的内容,驻留位=1,物理页帧号=W
- 重新运行中断的指令
4. 页面置换算法
目的:尽可能减少缺页中断的次数
定义:对于需要常驻内存的操作系统的关键页面,不在置换范围内,置换其他页面。
工作集:一个进程当前正在使用的逻辑页面集合(可能出现在内存中),会随着局部性区域的稳定和改变逐步变化。
- W(t,Δ):在当前执行时间段的所有页面组成的集合
- |W(t,Δ)|:页面数目
常驻集:在当前时刻,进程实际驻留在内存当中的物理页面集合(一定在内存中)。
- 当常驻集大小达到某个目标后,不会明显缺页
- 如果工作集的页面大部分在常驻集中,则进程会顺利进行,基本不会缺页中断。直到工作集发生波动。
4.1 局部页面置换算法:物理页帧固定,程序具有局部性原理
(1)最优置换算法OPT(不现实)
定义:对于每一个页面,假如能够预知之未来,预知下一次访问每页需要等待多久,选择等待时间最长的页面。
(2)先进先出算法FIFO(队列)
定义:选择在内存中驻留时间最长的页面。
特点:
- 实现简单
- 性能较差,可能会调出经常使用的页面
- 会产生Belady
Belady现象:在采用FIFO算法时缺页率反而提高。
栈算法:考虑到动态性,不会产生Belady现象
(3)最近最久未使用算法LRU(堆栈 / 链表)
定义:根据过去的情况,选择最久未使用的页面,推测它可能不经常使用
特点:
- 缺页次数较少
- 开销大
(4)时钟/最近未用页面置换算法NUR(循环链表)
定义:
当一个页面被装入时,访问位=0;如果该页面被访问,访问位=1。
把各个页面组织为循环链表,指针指向最先进来的页面。
选择指针所指的页面,如果访问位=1则重置为0并向下移动,如果访问位=0直接淘汰
(5)二次机会算法(修改时钟)
定义:避免大量写回脏页,让时钟保留脏页,淘汰只读页,从而脏页会有两次机会再淘汰
选择指针所指的页面,如果访问位=0和修改位=0直接淘汰
如果访问位=0 修改位=1则重置修改位=0并向下移动(多一次机会)
如果访问位=1 修改位=0则重置访问位=0并向下移动
如果访问位=1 修改位=1则重置访问位=0并向下移动(多两次机会)
(6)最不常用算法LFU(计数器)
定义:选择访问次数最少的页
特点:
- 可能一段时间后不再使用(计数器可以右移除2)
- 考虑的是访问次数越多越好
- LRU是考虑访问时间越短越好
算法 | 特点 | 顺序 |
---|---|---|
OPT | 不可能实现 | 动态变化 |
FIFO | 根据页面进入内存的时间置换 | 顺序固定 |
LRU | 根据页面最近访问时间置换 | 动态变化 |
CLOCK | 使用硬件模拟LRU | 动态变化 |
二次选择 | 考虑了写入外存的时间动态变化 | 动态变化 |
LFU | 根据页面访问次数置换 | 顺序固定 |
4.2 全局页面置换算法:物理页帧动态变化
工作集置换算法
定义:随着时间推移,移动工作集窗口,淘汰不在窗口大小内的页面,保证有足够多的空闲页
缺页率置换算法PFF
定义:在中断的时候进行判断,通过缺页率的变化动态调整常驻集大小。当缺页率过高时增加常驻集,当缺页率过低时减少常驻集
缺页率:缺页次数/内存访问次数
影响因素:
- 页面置换算法
- 分配到的物理页面数量
- 页面大小
- 程序的局部性
过程:
- 记录上一次缺失的时间 tlast,和下一缺失的时间 tcurrent,他们的时间间隔为T,如果T很小则证明缺页率高,页数过少,否则是页数过多
- 如果T>窗口大小,减少常驻集,移除工作集在这个时间段内没有引用的页
- 如果T<=窗口大小,增加常驻集,直接加入缺失页
性能:
有效访问时间=访存时间×命中率+缺页率×访问磁盘时间+缺页率×访问磁盘时间×写页率
抖动问题:多次缺页中断,频繁换页,影响性能。需要有一个合适的常驻集
- 平均页缺失时间(MTBF) = 缺失页的置换时间(PFST)
- 工作集内存大小
- 并发运行的程序数量