第四章 存储器管理
存储器层次结构
通用存储层次:CPU寄存器、主存、辅存、
层次 | 说明 |
---|---|
CPU寄存器 | 速度最快,容量极小,CPU直接操作 |
主存(RAM) | 存储正在运行的程序和数据 |
辅存 | 如硬盘、固态盘,速度慢但容量大 |
具体功能划分:
- 寄存器
- 高速寄存器(Cache)
- 主存储器
- 磁盘缓存(非实际存储介质)
- 固定磁盘
- 可移动存储介质
程序的装入和链接
存储器管理对象:内存
管理目标:
- 为用户使用存储器提供方便,用户只需要在自己的逻辑内存空间编程,不需要考虑真实内存的物理位置
- 为用户提供充分大的存储空间
- 提高内存的利用率,将尽量多的用户调入内存运行
逻辑地址与物理地址的含义、关系
程序进入内存的流程步骤
- 编译:源代码 -> 目标模块
- 链接:目标模块+库函数 -> 装入模块
- 装入:装入内存

程序的装入
主要讲的是逻辑地址 → 物理地址的映射时机:
装入方式 | 特点 |
---|---|
静态装入 | 程序运行前一次性装入内存,地址转换提前做好 |
动态装入 | 程序运行时,边运行边装入(延迟加载) |
动态链接 | 程序运行时才把需要的模块链接(例如 DLL) |
装入方式解决的是"地址映射"的问题
例:逻辑地址0x0004 → 映射成物理地址0x8044
绝对装入
绝对映射,程序中逻辑地址与内存物理地址完全相同
- 程序中所使用的绝对地址,既可在编译或汇编时给出, 也可由程序员直接赋予。
- 通常是在程序中采用符号地址 ,然后在编译或汇编时,再将这些符号地址转换为绝对地址。
- 特点:程序的逻辑地址与实际内存地址相同
可重定位装入
静态映射,在装入时对逻辑地址进行修改
在装入时对逻辑地址做一次性修改,以后不再改变

动态运行时装入
逻辑地址到物理地址的映射在程序运行时才执行
- 地址转换到程序真正要执行时才进行
- 装入内存后的所有地址都仍是相对地址
程序的链接
用于把多个模块整合成一个完整程序
链接方式 | 特点 |
---|---|
静态链接 | 编译时就把所有模块连接好,生成可执行文件 |
装入时链接 | 装入内存时完成模块链接 |
运行时链接 | 程序运行中需要哪个模块再链接(如调用共享库) |
静态链接方式(Static Linking)
在装入内存前已经链接成一个整体

装入时动态链接(Load time Dynamic Linking)
- 一边装入一边链接
- 便于修改和更新
- 便于实现对目标模块的共享
运行时动态链接(Run-time Dynamic Linking)
- 执行过程中,当发现一个被调用模块尚未装入内存时,立即由OS去找到该模块并将之装入内存, 把它链接到调用者模块
- 不用的目标模块不会被调入内存和被链接到装入模块
- 加快程序的装入过程,而且可节省大量的内存空间
连续分配方式
为每个用户程序分配连续的内存空间
- 单一连续分配(最简单)
- 整个内存分两个部分:操作系统 + 用户程序
- 只能运行一个程序
- 举例:早期 DOS 系统
- 固定分区分配(分段出租房)
- 内存分成若干固定大小的分区
- 每个分区只装一个程序
- 缺点:会有内部碎片(程序比分区小,浪费)
- 动态分区分配(按需切地)
- 内存根据程序大小,动态划分空间
- 更灵活,但容易产生外部碎片
单一连续分配
- 一个用户程序独占连续的内存用户空间
- 用于单用户,单任务的OS中
- 内存只分为两个区:系统区和用户区
- 一般对系统区 作保护,用基址寄存器做控制
固定分区连续分配
- 将内存划分多个区域,每个区域大小固定
- 每个区域只能装入一个程序
- 分区大小相等 的划分方法,一般用于多个相同任务
- 分区大小不等 的划分方法,根据实际任务大小分配

固定分区分配容易造成浪费

动态分区分配
- 无固定分区,在整块内存空间中动态分割
- 无用户程序,内存是一整块连续分区
- 根据程序大小,动态地分配连续的内存空间,分配的内存大小等于程序大小
要求解决的问题 :分区数据结构 、分配算法、 分配和回收操作
动态重定位分区分配
空闲分区表

空闲分区链

分配算法
常用内存分配算法(适用于动态分区)
算法名称 | 说明 |
---|---|
首次适应(First Fit) | 从头开始找,第一个够用的分区就分配 |
循环首次适应(Next Fit) | 上次分配到哪儿,从那开始找下一个 |
最佳适应(Best Fit) | 找最"刚好"的空闲分区,节省空间 |
最差适应(Worst Fit) | 找最大的分区,希望留下大块空闲区 |
快速适应(Quick Fit) | 常用分区大小分类,快速查找 |
首次适应
按顺序选择第一个满足要求的内存区域
优点:保留高地址的大部分空间
缺点:低地址存在很多小片无法利用的空间,查找时间长
循环首次适应
在上一次找到空闲分区的下一个分区开始寻找,找到第一个满足要求的内存区
优点:空闲分区在内存中分布均匀,查找时间短
缺点:缺乏大的内存空间
最佳适应
在所有空闲分区中查找与程序大小最相近的空闲分区
为了加快速度,可以把空闲分区从小到大排列
优点:提高内存使用率,保留大空闲去
缺点:仍然会存在小片无法利用的空闲分区
例子:假设有新程序F装入,大小为32K,当前已有程序B和D,最近一次空间分配是D
按照从上到下的顺序扫描

分配内存

回收内存
当一个程序结束,释放它的内存后,系统需要判断它左右是否有空闲区域:
-
左邻空闲 → 合并左边
-
右邻空闲 → 合并右边
-
左右都空闲 → 三块合并成一块
回收操作要维护数据结构(如空闲分区表)进行更新。
考虑三种情况:

伙伴系统
分割与回收均按2的K次幂进行分类操作
一种改进的动态分区方法,能方便合并和分裂:
- 内存总是以 2 的幂分割:512KB → 256+256 → 128+128......
- 分配时,如果当前块太大,就不断一分为二,直到足够小
- 回收时,如果两个伙伴都是空的,就合并成更大块
它能在动态分区的基础上,更高效地减少碎片.
可重定位分区分配
- 程序装入内存后,可以移动位置
- 系统需要有 地址重定位能力
- 有利于合并碎片、优化空间利用
对内存中正在使用的分区进行搬迁,使多个小的空闲分区(碎片)合并为一个大的空闲分区

动态重定位的实现

动态重定位分区分配算法

练习题
已知当前内存状态表如下,现有作业D、E、F处于后备队列,分配顺序是D到E再到F,大小分别为36K、9K和23K,请用动态分区分配算法FF、BF进行分配: 请写出分配后D、E、F在内存的起址和末址,如果有作业未能分配空间请说明 在分配完后再回收作业B,请写出包含作业B的空白分区的起址和末址。
|---------|----------|----------|--------------|
| 分区号 | 大小 | 起址 | 状态 |
| 0 | 100K | 0 | 系统区 |
| 1 | 25K | 100K | 空闲 |
| 2 | 55K | 125K | A 占用 |
| 3 | 50K | 180K | 空闲 |
| 4 | 30K | 230K | B 占用 |
| 5 | 40K | 260K | 空闲 |
对换
提高内存利用率的有效措施
把内存中暂时不能运行 的进程或者暂时不用的程序和数据,调出到外存上,以便腾出足够的内存空间,再把已具备运行条件的进程或进程所需要的程序和数据,调入内存。
两种对换方式
整体 对换:以进程为单位
部分 对换:以页或段为单位
对换空间管理
- 将外存 分为文件区与对换区
- 对换区采用连续存储方式
- 整体对换 采用类似连续分配的方式管理对换区,包括空间的分配与回收
对换操作包括进程换入、进程换出
进程换出
- 系统选择处于阻塞态且优先级最低的进程作为换出进程
- 启动盘块,将进程的程序和数据传送到磁盘的对换区
- 若传送无错误,回收内存空间
- 对该进程的PCB做相应的修改。
进程换入
- 系统定时查看所有进程状态,找出**"就绪"状态但已换出**的进程
- 对换出时间**(换出到磁盘上)最久** 的进程进行换入操作
- 直至已无可换入的进程或无可换出的进程为止。
基本分页存储管理方式
引入:非连续分配,离散地分布在内存不同位置
把程序分成一页一页(逻辑上),放进内存的空闲小块(物理上)里运行,不需要连续空间!
基本概念
- 页 面:逻辑 上的划分,进程空间管理上的划分,简称页
- 物理 块:物理上的划分
名称 | 是什么? | 属于谁? | 大小 |
---|---|---|---|
页(Page) | 把程序按固定大小划分成一页一页 | 逻辑空间(程序视角) | 固定,如 2KB |
块(Frame) | 把内存按固定大小划成一块一块 | 物理空间(内存视角) | 固定,如 2KB |
一页程序放到一个块中,正好对应!(大小一样)
页 是操作系统分配内存的最小单位(进程的最后一页装不满一块形成了不可利用的碎片)
页与物理块的关系
- 页的大小与物理块大小完全相等
- 进程任何一个页都可以装入内存的任何一个物理块
- 进程除了最后一个页可能会产生碎片,其他页都是刚好装入各个物理块中
- 各个页离散地分布在不同物理块中
- 页的编号在逻辑地址上是连续 的,在物理块分布上是离散的
页大小: 一般是2的n次幂,通常为512B~8KB
地址结构
页面:逻辑上的划分,进程空间管理上的划分,简称页
物理块:物理上的划分
逻辑地址 = 页号(Page No) + 页内地址(Offset)
例子:如果页大小是 2KB(=2048),逻辑地址 3000:
- 页号 = 3000 ÷ 2048 = 1
- 页内地址 = 3000 % 2048 = 952

地址计算方法
地址为A,页面大小为L,则页号P和页内地址d,计算如下(页内地址也就是页内偏移量)

例:A=2170B,L=1KB 则 P=2, d=122
页表
记录进程 每一页在内存 存放的块号( 记录每一页(逻辑页)对应的是哪个物理块**)**
页面与物理块的对应关系

页表的管理
- 页表数据存放在内存
- 页表的起址和长度存放在PCB中
- 地址转换时,页表的起址和长度送入页表寄存器PTR
地址变换
- 进程访问某个逻辑地址时,分页地址机构自动将逻辑地址分为页号和页内地址
- 页号大于页表长度,越界错误
- 根据页号计算位置,从页表中查物理块号
- 页内地址直接对应块内地址
- 通过物理块号和块内地址得到物理地址
- 根据物理地址读取数据

CPU 给出逻辑地址(页号 + 页内偏移)
操作系统查页表,从页号查到块号
物理地址 = 块号 × 块大小 + 页内偏移
练习题
某系统采用分页式存储管理,页大小为2KB。已知进程A的逻辑地址空间为4个页,内存分配如下页表所示,求逻辑地址4832的物理地址。(所有数据都是十进制)
|--------|--------|
| 页号 | 块号 |
| 0 | 17 |
| 1 | 8 |
| 2 | 25 |
| 3 | 19 |
地址变换缺点
- 需要访问两次内存才能取出数据
- 一次访问页表,查找物理块号,计算物理地址
- 一次根据物理地址读取数据
具有快表的地址变换
快表是一个硬件缓存,专门存最近用过的页表项
- 快表是高速存储器 ,具有并行查找功能
- 快表访问速度一般是内存的几倍
- 将页表部分内容存在快表,一般存放当前使用的页表项
- 快表主要用于减少逻辑地址到物理地址的转换时间
带快表的地址变换过程
- 进程访问某个逻辑地址时,分页地址机构自动将逻辑地址分为页号和页内地址
- 页号大于页表长度,越界错误
- 页号送入快表,查找物理块号
- 若快表找到,送入物理地址寄存器
- 否则在从页表查找物理块号,送入物理地址寄存器
- 页内地址直接对应块内地址
- 通过物理块号和块内地址得到物理地址
- 根据物理地址读取数据

先查快表(TLB),命中就直接找到块号(快!)
快表没命中,再查页表(慢一些)
然后再去内存中访问对应块的数据
具有快表的地址变换举例
- 快表访问时间为20ns,内存访问为100ns
- 若快表查找成功,包括读数据总时间为120ns
- 若快表查找失败,得到总时间为220ns

快表:先求快表查找成功和失败所需的总时间,再使用命中率求有效访问时间
(T = 命中率 * 快表查找成功总时间 + (1-命中率) * 快表查找失败总时间)
单级页表
单级页表缺陷
- 页表一般是数组的形式,空间分配属于连续分配
- 页表大小不能超过单个物理块大小
- 当逻辑地址空间很大时,导致页表占用内存空间很大
- 例如地址长度32位,可以得到最大空间为4GB,页大小4KB,最多包含4G/4K=1M个页
2^32=2^30 * 2^2 = 4GB (地址长度32位,可以得到最大空间为4GB)
- 若每个页表项占用4个字节,则页表最大长度为4MB,即要求内存划分出连续4MB的空间来装载页表,而且页表采用的是连续分配,不是分页分配
页表大小 = 页数 * 每个页表项占用字节数 = 1M * 4 = 4MB
解决方法
- 采用离散分配方式的管理页表
- 将当前需要的部分页表项调入内存, 其余的页表项仍驻留在磁盘上,需要时再调入
两级页表
对页表本身采用分页式管理,对页表本身增加了一层页表管理。
两级页表的逻辑地址结构与地址变换
注意:页大小就是页表大小,一张页表只能装在一个页中


多级页表
- 32位系统采用两级页表结构是合适的
- 对于64位系统,页大小4KB,则页内地址为12位,外部页内地址也为12位,外部页号则有40位,即最多可以有1024G个页表项,实际并不需要这么多
- 64位系统最大支持空间264=1844744 TB ,目前实际只使用48位,采用三级页表就可以了
练习题
-
一个32位地址的计算机系统使用二级页表,虚地址被分为9位顶级页表,11位二级页表和偏移.请问: 1)页面长度是多少? 2)空间共有多少个页面?
-
在一个分页存储管理系统中,逻辑地址长度为16位,页面大小为4096字节,现有一逻辑地址为2F6AH,且第0、1、2页依次存在物理块10、12、14号中,问相应的物理地址为多少?
-
设一页式管理系统,向用户提供的逻辑地址空间最大为16页,每页2048字节,内存中共有8个存储块。试问逻辑地址至少应为多少位?内存空间有多大?
-
假设页面的大小为4KB,一个页表项用4B.若要求用页表来管理地址结构为36位的虚拟地址空间,并且每个页表只占用一页。那么,采用多级页表结构时,需要几级才能达到管理的要求?
5.有一基本分页存储管理系统,假定页面大小为1024字节,页表采用离散方式放在内存中。每个页表项占用4个字节。在忽略页表及系统区等占用空间的条件下:(所有数据都是十进制)
- 若采用一级页表,系统能支持的逻辑空间最多为多少?
- 若采用二级页表,系统能支持的逻辑空间最多为多少?
- 二级页表,现有逻辑地址为542783,求该地址对应的外层页号,外层页内地址和页内地址?
基本分段存储管理方式
基本概念
分段是指将一个进程划分为多个具有逻辑意义而且相对独立的部分
例如主程序段、数据段、堆栈段、子程序段等
X86常见的段基址:CS、SS、DS、ES
每个段都是从0开始的独立逻辑地址空间
引入分段的好处
- 方便编程
- 信息共享
- 信息保护
- 动态增长
- 动态链接
分段的地址结构
每个段都有独立的名称,为了管理方便,用段号表示
在逻辑地址意义上,每个段地址包含两部分
所以段地址是二维结构

段表
段号+段长+基址

段地址变换
- 进程访问某个逻辑地址时,先取得段号
- 若段号大于段表长度,越界错误
- 查段表得到段开始地址和段长度
- 若段内地址大于段长度,越界错误
- 通过段开始地址和段内地址得到物理地址
- 根据物理地址读取数据

具有快表的分段地址变换
将段表放入快表中
由于段的数量远少于页的数量 ,段表装入快表的百分比要比页表大 ,所以分段的快表命中率也高 ,一般比常规内存访问慢10%~15%
为什么"段的数量远少于页的数量"?
答:
因为段是按"功能模块"划分的,而不是固定大小切割:
例子:代码段、数据段、栈段、堆段、常量段,一般也就 4~10 个段,不多!
而分页是对进程平均切块,不管逻辑结构,所以一个大程序可能被分成 几百、上千个页!
为什么"段表装入快表的百分比要比页表大"?
答:
段数量少,就更容易"全部"装入快表里,命中率就高。
即使快表命中了,也有至少两个操作步骤 ,所以:分段 + 快表 ≈ 比直接访问内存 慢10%~15%。(但比不用快表快多了!)
分页与分段的区别
- 页 是信息的物理 单位,满足系统空间管理需要。分页实现离散分配方式,以消减内存的外零头, 提高内存的利用率。段 是信息的逻辑单位,满足用户需要。
- 页 的大小固定 ,由系统 决定。段 的长度不固定 , 由用户决定。
- 分页 的作业地址空间是一维 的。分段 的作业地址空间则是二维的。
比较项 | 分页 | 分段 |
---|---|---|
划分单位 | 固定大小的页 | 逻辑结构划分 |
地址结构 | 页号 + 页内偏移 | 段号 + 段内偏移 |
是否有逻辑意义 | ❌ 没有 | ✅ 有 |
内存分配 | 更容易管理碎片 | 更灵活,支持模块化 |
页表/段表 | 一般较大 | 一般较小 |
信息共享
- 段是有意义的信息逻辑 单位,含有一组相对完成独立的信息
- 多个进程共享一个具有独立意义的段 ,实现很简单,只要在各自段表加入相同段基址和段长度就可以了
- 例如Windows动态链接库中的纯代码段,可以被多个进程共享


练习题
某系统采用分段式存储管理,在一个进程中,它的段表如下所示,求逻辑地址为(2,895)对应的物理地址(所有数据都是十进制)
|--------|----------|
| 段号 | 开始地址 |
| 0 | 80K |
| 1 | 12K |
| 2 | 25K |
| 3 | 72K |
段页式管理
段页式管理的引入
- 段面向用户程序需要,段长度不固定
- 段需要分配连续空间,存在连续分配的缺点,例如易产生碎片
- 结合段式和页式两者管理优点,既能节省内存空间,提高内存分配效率;又能兼顾用户程序需要
段页式管理的机制
- 分段与分页机制的结合
- 先将用户程序划分为多个有逻辑意义的段,再将段划分为多个页
- 段页式管理需要设置段表和页表
- 每个段都对应一张页表,因此段表存放了每张页表的开始地址和页表长度
程序被按段划分
每段再被分页
系统中:
有一张段表:找段的页表起始地址
每段有一张页表:找页所在的块
逻辑地址 = 段号 + 页号 + 页内偏移
1️⃣ 从段号查"段表" ⇒ 得到该段页表的地址
2️⃣ 用页号查"页表" ⇒ 得到对应的物理块号
3️⃣ 用块号 + 页内偏移 ⇒ 计算出物理地址
段页式管理的地址结构

段页式的地址映射

段页式的地址变换过程
- 进程访问某个逻辑地址时,先取得段号
- 段号大于段表长度,越界错误
- 查段表,得到页表开始地址
- 在页表内,根据段内页号查物理块号
- 页内地址直接对应块内地址
- 通过物理块号和块内地址得到物理地址
- 根据物理地址读取数据

段页式管理中的快表
- 原有的地址变换需要访问三次内存:段表+页表+数据
- 增加一个高速缓冲寄存器,每次访问以段号和页号 为索引去检索高速缓存,从中找到相应的物理块号。
- 若找不到,再执行三次访问。
练习题
在一个段页式存储管理系统,页面大小为1024字节。在一个进程中,它的段表、页表如下所示,求逻辑地址为(1,2099)对应的物理地址。
|--------|----------|---|--------|----------|---|--------|----------|---|--------|----------|
| 段表 ( 第 2 块 ) || | 段内页表 ( 第 76 块 ) || | 段内页表 ( 第 33 块 ) || | 段内页表 ( 第 52 块 ) ||
| 段号 | 页表首址 | | 页号 | 内存块号 | | 页号 | 内存块号 | | 页号 | 内存块号 |
| 0 | 76 | | 0 | 18 | | 0 | 65 | | 0 | 6 |
| 1 | 33 | | 1 | 22 | | 1 | 13 | | 1 | 98 |
| 2 | 52 | | 2 | 36 | | 2 | 40 | | 2 | 82 |
请求分段存储管理方式
请求分段中的硬件支持: 段表机制、缺段中断机构、地址变换机构
段表机制

- 段名、段长、基址:原有
- 存取方式:执行、只读、读/写
- 访问字段:一段时间内访问次数
- 修改字段:调入后是被修改过
- 存在位:是否已在内存
- 增补位:是否做过动态增长
- 外存地址:本段在外存的起始盘块号
缺段中断机构
- 一条指令可能发生多次缺段中断
- 整条指令只会在一个段内
- 整个数据只会在一个段内

地址变换机构

分段的共享与保护
共享段表
- 共享进程计数count:记录共享进程数,影响段回收操作
- 存取控制字段:记录访问权限,文件主、其他进程
- 段号:不同进程可以使用不同段号共享同一段

共享段的分配
- 为共享段分配空间,调入共享段
- 首个调用共享段的进程段表中填写记录
- 在共享段表中增加一项,填写信息,
- 设count为1
- 若有其他进程调用共享段,无需再分配空间
- 在调用进程段表中增加表项,填写共享段的物理地址
- 在共享段表中填上调用进程的进程名、存取控制等,
- count+1
共享段的回收
- 当某进程不需要共享段
- 删除该进程段表中对应共享的表项
- 删除该进程在共享段表中的有关记录
- count-1
- 如果count为0,系统回收该共享段的物理内存,取消共享段表,此时已没有进程使用该段
共享段的特点
- 由第一个调用共享段的进程请求系统分配空间
- 由最后一个调用共享段的进程请求系统回收空间
分段保护
(1)越界检查
(2)存取控制检查:只读 、只执行、读/写
(3)环保护机构
- 程序可以访问驻留在相同环或较低特权环中的数据
- 程序可以调用驻留在相同环或较高特权环中的服务
(图中环2为较低特权环,环0为较高特权环)

虚拟存储器
常规存储器管理面临的问题
- 单个作业很大,要求的内存超过总容量
- 大量作业要求进入,要求总量超过总容量,使得并发数量受限制
常规存储器管理方式的特征
- 一次性:内存浪费,每个作业都是一次性全部装入内存
- 驻留性:占用资源,不使用部分长期占用内存
局部性原理
- 程序执行时, 除了少部分的转移和过程调用指令外, 在大多数情况下仍是顺序执行的
- 过程调用将会使程序的执行轨迹由一部分区域转至另一部分区域, 但经研究看出,过程调用的深度在大多数情况下都不超过5
- 程序中存在许多循环结构, 这些虽然只由少数指令构成, 但是它们将多次执行
- 程序中还包括许多对数据结构的处理, 如对数组进行操作, 它们往往都局限于很小的范围内
局限性
**时间局限性:**如果程序中的某条指令一旦执行, 则不久以后该指令可能再次执行;如果某数据被访问过, 则不久以后该数据可能再次被访问。 时间局限性的典型是在程序中存在着大量的循环操作。
空间局限性: 一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能集中在一定的范围之内 典型情况便是程序的顺序执行**。**
虚拟存储器定义
所谓虚拟存储器, 是指具有请求调入功能和置换功能, 能从逻辑上对内存容量加以扩充的一种存储器系统
- 其逻辑容量由内存容量和外存容量之和所决定
- 其运行速度接近于内存速度
- 成本接近于外存
虚拟存储器的虚拟特性
- 对内存空间的虚拟,将大容量的外存(交换区)作为内存管理
- 对进程地址空间进行虚拟,允许进程有几乎无限大的地址空间
虚拟存储器的实现
分页请求系统
- 在基本分页系统上增加请求调页功能和页面置换功能
- 发生缺页就请求调页
- 内存不足,就换出暂时不运行的页面
- 硬件支持:页表机制、缺页中断、地址变换
请求分段系统
- 在基本分段系统上增加请求调段功能和分段置换功能
- 调入即将运行的段和换出暂不运行的段
- 硬件支持:段表机制、缺段中断、地址变换
虚拟存储器的特征
- 多次性:一个进程被分为多次调入内存运行
- 对换性:允许进程在运行过程中换入、换出
- 虚拟性:从逻辑上扩充内存容量
请求分页存储管理方式
请求分页中的硬件支持:页表机制、缺页中断机构、地址变换机构
页表机制
纯分页的页表机制上增加若干项
- 状态位:指示本页是否已经调入内存
- 访问字段:记录本页在一段时间内访问的次数
- 修改位:本页在调入内存后是否被修改过
- 外存地址:本页在外存中的物理位置,一般是物理块号
|--------|----------|---------------|----------------|---------------|----------|
| 页号 | 物理块号 | 状态位 P | 访问字段 A | 修改位 M | 外存地址 |
缺页中断机构
当要访问的页面不在内存便产生缺页中断,以请求OS将所缺的页调入内存。
缺页中断与一般中断的共同点:
- 保存CPU现场
- 分析中断原因
- 缺页中断处理
- 恢复CPU现场
缺页中断与一般中断的区别:
- 缺页中断可能发生在指令执行过程中
- 一条指令执行期间,可能发生多次缺页中断,最多可达6次
地址变换

地址变换过程
- 将逻辑地址划分为页号和页内地址
- 页号的越界检查
- 从快表查找块号
- 若找到,合并块号和块内地址得物理地址,修改访问位,若是写操作,设修改位为1
- 若找不到,查页表
- 若页面已在内存,将页号与块号调入快表,跳到步骤4
- 若页面不在内存,调用缺页中断,跳到步骤6
内存分配策略和分配算法
由于每个进程都不是一次性完全装入内存,而且内存的物理块数量有限,因此需要确定每个进程的物理块分配
- 最小物理块数的确定
- 物理块的分配策略
- 物理块的分配算法
最小物理块数的确定
- 是指能保证进程正常运行所需的物理块最少数量
- 取决于指令的格式、 功能和寻址方式
- 单地址指令+直接寻址,最少物理块数为2。一块存放指令,一块存放数据
基础款:单地址指令 + 直接寻址 (最少需要 2 块)
单地址指令: 一条指令主要做一件事(比如
ADD R1, [A]
, 意思是把内存地址A
处的值加到寄存器R1
上)。直接寻址: 指令里直接写了操作数在内存中的具体地址
A
。为什么需要 2 块?
块 1: 存放指令本身 。CPU 必须先把这条
ADD
指令从内存读出来,才知道要做什么。块 2: 存放操作数 。CPU 执行
ADD
时,需要去地址A
把那个数读出来(或者写回去)。地址A
指向的内存单元必须在这个块里。关键点: 指令执行过程中,CPU 会先后访问两个不同的内存位置(指令地址、操作数地址)。这两个位置很可能在不同的页面,所以最少需要 2 个物理块来装这两个页面,保证指令能完整执行完。
- 系统支持间接寻址时,则至少要求有3个物理块
升级款:系统支持间接寻址 (最少需要 3 块)
间接寻址: 指令里的地址
A
不是操作数本身的位置,而是存放操作数真实地址的地址 !有点像"指针的指针"。比如指令是LOAD R1, @B
,@
表示间接寻址。意思是:
先去地址
B
取出一个值,假设这个值是C
。然后
C
才是操作数真正的内存地址。最后去地址
C
把操作数加载到R1
。为什么需要 3 块?
块 1: 存放指令本身 (
LOAD R1, @B
)。块 2: 存放第一级地址
B
。CPU 执行指令时,需要先访问B
去取里面的内容C
。B
指向的内存单元在这个块里。块 3: 存放操作数本身 。地址
C
(从B
处取出的值) 指向的内存单元,里面放着最终要加载到R1
的操作数。⚡️ 关键点: 执行一条间接寻址指令,CPU 需要访问三个不同的内存位置 (指令位置、一级地址位置
B
、最终操作数位置C
)。这三个位置最坏情况会分布在三个不同的页面,所以最少需要 3 个物理块
- 若多字节指令,指令本身跨两个页面,源地址和目标地址也可能跨两个页面,共涉及6个页面
复杂款:多字节指令 + 跨页操作数 (理论最坏情况需要 6 块)
背景: 指令本身可能比较长(多字节),操作数(源数据、目标地址)也可能是很长的数据(比如一个大结构体、一个长字符串)。
跨页问题: 内存是按固定大小的页面划分的。一个指令或一个操作数,如果它跨越了两个页面的边界 存放,那么访问它就需要读取两个页面。
最坏情况分析 (为什么可能是 6 块):
指令本身跨页 (需要 2 块): CPU 取指令时,指令的头几个字节在页面 X 的末尾,剩下的字节在页面 Y 的开头。必须把页面 X 和 Y 都装入内存,CPU 才能完整读到这条指令。
源操作数跨页 (需要 2 块): 指令要读取的数据(源操作数)也可能横跨两个页面(比如页面 Z 末尾和页面 W 开头)。需要把页面 Z 和 W 都装入内存才能读到完整数据。
目标操作数跨页 (需要 2 块): 指令要写入结果的地方(目标操作数)同样可能横跨两个页面(比如页面 U 末尾和页面 V 开头)。需要把页面 U 和 V 都装入内存才能写入完整结果。
6 块怎么来的?
指令跨页(2块)
+源操作数跨页(2块)
+目标操作数跨页(2块)
= 6 块。
物理块的三种分配策略
- 固定分配局部置换 :每个进程的物理块数量固定,每次页面置换都在进程自身的物理块中进行
- 可变分配全局置换:OS保留一定的空闲物理块,根据进程需要动态分配。若无空闲物理块,页面置换选择任一进程的物理块,由算法决定
- 可变分配局部置换:分配同上,页面置换在进程自身的物理块中进行
分配策略的评价指标:并发进程数、缺页率
- 并发进程数越多
- 每个进程的缺页率越低
物理块分配算法
(1)平均分配:所有空闲物理块平均分配给各个进程
例系统有100个物理块,有5个进程在运行时,每个进程可分得20个物理块 若其中一个进程大小为200页,只分配20个块,则缺页率很高 若一个进程只有10页,则有10个物理块闲置未用.
(2)按比例分配:根据进程大小按比例分配物理块
- n个进程,每个进程的页面数为Si
- 可用物理块总数为m
- 每个进程所能分到的物理块数为bi
- bi取整且必须大于最小物理块数
(3)按优先权分配:对重要的、紧迫的作业分配较多的空间
将空闲物理块分成两部分:一部分按比例地分配给各进程;另一部分则根据各进程的优先权,适当地增加其相应份额
练习题
例如A\B\C\D四个进程,分别需要100、200、300、400个物理块,现有500个物理块,则平均分配、比例分配和优先分配的结果
调页策略
何时调入页面
- 预调入页策略:发生缺页时,一次性调入多个相邻页
- 请求调页策略:发生缺页时,只调入缺页
何处调入页面
外存分为文件区和对换区,对换区采用连续分配,文件区采用离散分配,对换区的磁盘I/O速度比文件区高
- 全部从对换区调入,要求进程运行前将所有文件从文件区拷贝到对换区
- 先从文件区调入;若页面被修改则换出时放入对换区,以后从对换区调入;未修改页面下次仍从文件区调入
- 未运行页面从文件区调入;运行过且被换出的页面从对换区调入
页面调入过程
- 若访问页面未在内存,向CPU发出一缺页中断
- 中断处理程序首先保留CPU环境,分析中断原因,转入缺页中断处理程序。
- 缺页中断处理程序查找页表,得到该页在外存的物理块号
- 若内存能容纳新页,则启动磁盘I/O将缺页调入内存
- 若内存已满,按照某种置换算法选出一页准备换出;如果该页未修改,该页不必写回磁盘;若该页已被修改, 则必须写回磁盘,调到步骤4
- 修改页表,置存在位为1,并将此页表项写入快表中
- 利用修改后的页表, 形成要访问数据的物理地址,读取内存数据
页面置换算法
页面置换算法的设计目标
- 具有较低的页面更换频率------低缺页率
- 找出以后不再访问的页面或者较长时间不再使用的页面
算法种类:最佳置换算法、先进先出算法、LRU算法、Clock算法、其他算法
最佳置换算法
- 选择的页面:不再访问的或者较长时间不再使用
- 优点:保证最低的缺页率
- 缺点:不可能真正实现,只作为其他算法评价参考
- 特点:"往后看",看未来,理论上的算法,不可行

先进先出(FIFO)页面置换算法
- 淘汰最先进入内存的页面,即选择内存驻留时间最长的
- 需要使用指针标识停留最久的位置
- 优点:算法简单;缺点:性能不佳 特点:
- 只看"进入顺序"

最近最久未使用(LRU)置换算法
- 选择最近最久未使用的页面
- 增加访问字段记录各个页面未被访问的周期数
- 优点:性能较好;缺点:需要较多硬件支持
- 特点: "向前看",看过去的使用情况

LRU置换算法需要硬件支持
LRU硬件要解决的问题
- 进程各个页面有多久未被访问
- 如何快速找到最近最久未使用的页面
LRU硬件:移位寄存器、堆栈
- 移位寄存器: 每个寄存器记录进程在内存中每页的使用情况
- 数据格式: R=Rn-1Rn-2Rn-3 ... R2R1R0
- 页面被访问一次,最高位Rn-1置1,每隔一定时间,寄存器右移一位
- R值最小的页面是被置换页面
移位寄存器
记录进程在内存中每页的使用情况

堆栈
- 采用特殊的栈来保存当前使用的各个页面号
- 栈顶保留的是最新被访问的页
- 栈底保留的是最久未被访问的页,即置换目标

练习题
在一个请求分页系统中,假定系统分配给一个进程的内存块数为3,进程的页面走向为1、3、1、2、4、2、1、4、5、3、1、2。若采用最近最久未使用置换算法(LRU),请画图表示页面置换过程并计算缺页次数。 假定开始时物理块全为空,每次调入页面都作为一次缺页处理
简单的Clock置换算法
- LRU算法的近似算法,也称为最近未用算法。
- 为每页设置一访问位,当被访问则设置为1,未访问为0。

改进型Clock置换算法
每个页面有访问位A和修改位M
两个位组合成四种类型页面
- A=0, M=0:最近未被访问,又未被修改,最佳淘汰页
- A=0, M=1:最近未被访问,但已被修改页。
- A=1, M=0:最近已被访问, 但未被修改。
- A=1, M=1:最近已被访问且被修改,最不应淘汰页。
改进型Clock的执行过程
- 从当前指针位置开始扫描循环队列,寻找第1类页面,不改变访问位A,将遇到的第一个这类页面作为淘汰页
- 第一步查找失败,寻找第2类页面,将遇到的第一个这类页面作为淘汰页。在扫描期间,所有扫描过的页面的访问位A都置0。 所有3类页面变成1类页面,4类页面变成2类页面。(访问位A改为1)
- 第二步失败,重复第一步
- 如果仍失败,再重复第二步,此时就一定能找到被淘汰的页。

优点:减少了磁盘的I/O操作次数
缺点:可能需要几轮扫描,增加了系统开销
特点:使用两个指标判断,访问位+修改位
练习题
在一个请求分页系统中,已知某进程有4页在内存,页码依次为12,23,31,48,其A、M位分别为(1,1)、(1,0)、(1,0)、(1,1),若采用改进型Clock置换算法,选择哪页淘汰?选择完成后,四个页的A、M位分别为多少?
其它置换算法
最少使用(LFU: Least Frequently Used)置换算法
对每个页面设置一个字段(移位寄存器),用来记录页面被访问的频率
页面缓冲算法
- 采用可变分配和局部置换方式
- 当一个进程换进换出频率很低时,选择页面淘汰,以备其他进程使用
- 被淘汰页面若发生修改,放入已修改链表,否则放入空闲链表
- 修改链表的页面积累一定数量,一次性写回硬盘
第五章 设备管理
I/O 系统
设备管理对象:I/O设备
必要性:设备种类繁多、物理特性多样、控制复杂、与主机速度不匹配
基本任务:完成I/O请求,提高I/O速率,提高I/O设备利用率
主要功能:缓冲区管理、设备分配、设备处理、虚拟设备、实现设备独立性
I/O设备种类
(1)按传输速率分类
低速设备,速率1KB/s以下,典型设备有键盘、 鼠标器、语音的输入和输出等设备
中速设备,速率1KB---100KB/s,典型设备有行式打印机、激光打印机
高速设备,速率100KB/s以上,甚至几十兆字节, 典型设备有磁带机、 磁盘机、 光盘机等
(2)按信息交换单位分类
块设备,Block Device,用于存储信息,以数据块为单位,属于有结构设备。典型设备是磁盘
- 特征是传输速率较高,通常每秒钟为几兆位
- 另一特征是可寻址,即对它可随机地读/写任一块
- 磁盘设备的I/O常采用DMA方式。
字符设备,Character Device,用于数据的输入和输出 单位是字符, 故称为字符设备。无结构的数据I/O
- 特征是传输速率低
- 另一特征是不可寻址
- 常采用中断驱动
(3)按共享属性分类
独占设备:一段时间内只允许一个用户使用
共享设备:可同时允许多个用户使用,并发
虚拟设备:采用软硬件技术将一台物理设备变为多个逻辑设备
设备控制器
- 一个计算机实体
- CPU与I/O设备的接口
- 控制多个I/O设备
- 实现I/O设备与主机的数据交换
- 可编址设备,通过I/O地址识别不同的设备
I/O通道
I/O通道是一种特殊的处理机
- 具有执行I/O指令的能力
- 通过执行通道(I/O)程序控制I/O操作
- 指令类型单一,主要限于与I/O操作有关的指令
- 没有自己的内存,通道程序放在主机内存中
通道类型:
- 字节多路通道
- 数组选择通道
- 数组多路通道
I/O通道的瓶颈
存储器
│
├── 通道1 ── 控制器1 ── 设备1、设备2
│ └─ 控制器2 ── 设备3、设备4
│
└── 通道2 ── 控制器3 ── 设备5、设备6
└─ 控制器4 ── 设备7
-
每个通道(通道1和通道2)都连接两个控制器,控制器下还有多个设备,这样每个通道的负载较高。
-
多个控制器并发传输数据时,通道带宽有限,可能导致通道竞争和传输延迟,出现拥塞。
-
控制器1和控制器2共享通道1;控制器3和控制器4共享通道2。
-
如果多个设备同时发起IO请求,控制器也会成为瓶颈,尤其是当控制器没有足够的并发处理能力时。
多通路I/O系统
如一个存储器连接两个通道,通道1连接控制器1和控制器2,通道2也连接控制器1和控制器2,而2个控制器都连了4个I/O设备。
存储器
│
├── 通道1 ── 控制器1 ── 设备1
│ | ├─ 设备2
│ | ├─ 设备3
└── 通道2 ── 控制器2 ── 设备4
一条通路包括:通道------控制器------I/O设备
-
一条通道或一个控制器发生故障,系统仍可通过另一条路径访问I/O设备,不会造成服务中断。
-
系统可以将I/O请求分布到不同路径上,实现负载均衡。
-
如果操作系统和硬件支持路径并行访问,可提升总I/O吞吐量。
总线系统

现代总线设计:存储总线(北桥)+ I/O总线(南桥)
北桥 负责高速设备(CPU、内存、显卡)的通信,
南桥负责低速设备(硬盘、USB、音频、网络等)的通信。
| 总线类型 | 描述 | 属于哪个桥 |
| 系统总线 | CPU ↔ 内存 | 北桥 |
| AGP/PCIe总线 | CPU ↔ 显卡 | 北桥 |
| I/O总线 | 外设(硬盘、USB等) ↔ CPU | 南桥 |
ISA/LPC总线 | 传统低速外设(BIOS、超级I/O) | 南桥 |
---|
I/O控制方式
(1)I/O通道控制方式
- 以一组数据块的读/写作为控制和管理单位
- 实现CPU、通道和I/O设备三者的并行操作
- CPU需向I/O通道发送指令,给出要执行的通道程序的首址和要访问的I/O设备
- 通道执行 通道程序,完成CPU指定的I/O任务
(2)程序I/O方式
(3)中断驱动I/O控制方式
(4)直接存储器访问DMA I/O控制方式

缓冲管理
缓冲的引入
- 缓和CPU与I/O设备间速度不匹配的矛盾
- 减少对CPU的中断频率, 放宽对CPU中断响应时间的限制
- 提高CPU和I/O设备之间的并行性

单缓冲

运行周期:Max(C, T) + M
单缓冲系统的处理过程分为三个步骤(顺序执行):
-
I/O 设备 → 缓冲区 :数据从设备读取,放入缓冲区,时间为
T
。 -
用户进程处理缓冲区数据 :即用户程序工作,处理缓冲区数据,时间为
C
。 -
缓冲区 → 用户工作区 :将缓冲区的数据拷贝到用户工作区,时间为
M
。
第一阶段:Max(C, T) ------ 并发部分的"瓶颈时间"
-
系统可以边I/O读入(T)边用户处理数据(C),但只能等待两者中较慢的那一个完成。
-
如果 C > T,那么得等用户处理完。
-
如果 T > C,那么得等数据传输完。
-
-
所以这一阶段的耗时为
Max(C, T)
。
举例:
-
如果 T = 5ms,C = 3ms → 等待T = 5ms;
-
如果 T = 2ms,C = 4ms → 等待C = 4ms。
第二阶段:M ------ 必须串行的数据拷贝
-
用户必须等数据从缓冲区复制到工作区;
-
这个过程不能并行,只能在第一阶段完成之后进行;
-
所以 这个 M 是强制串行追加的时间。
双缓冲

运行周期:Max(C+M, T)
- C+M<T:主机速度快,主机等待,磁盘连续输入
- C+M>T:磁盘速度快,磁盘等待,主机连续运行
相比单缓冲,双缓冲的核心在于两个缓冲区交替工作,允许真正的"并行":
-
一个缓冲区用于 I/O设备向其中写入数据(T);
-
另一个缓冲区中的数据被 主机读取和处理(C + M);
-
两个过程可以同时进行(并行)
循环缓冲

三类缓冲区:空白、装满、执行
- 空白:缓冲区尚未写入数据,可写
- 装满:已写入数据,等待被处理
- 执行:正在被主机处理中的缓冲区
三个指针:指向三类缓冲区,Nexti, Nextg, current
- Nexti:指向下一个可用于输入(写入)的空白缓冲区
- Nextg:指向下一个可用于获取(读取)的已填满缓冲区
- current:指向当前正在处理的缓冲区(执行中)
两个进程: 读/写数据Getbuf;修改状态Releasebuf
-
写入进程(I/O 设备):
-
使用
Getbuf()
来找一个空白缓冲区; -
写入数据后调用
Releasebuf()
把状态设为"装满"。
-
-
读取进程(主机/CPU):
-
使用
Getbuf()
找一个"装满"的缓冲区来读取; -
读完后调用
Releasebuf()
把状态改回"空白"。
-
进程同步控制:
(1)Nexti赶上Nextg
-
写入进程写得太快,还没被读取进程读取;
-
此时
Nexti
追上了Nextg
,意味着所有缓冲区都处于"装满"状态。 -
写入进程必须 等待;
-
一直到读取进程释放了至少一个缓冲区(变为空白),才能继续写。
(2)Nextg赶上Nexti
-
读取进程读得太快,还没来得及写入新数据;
-
此时
Nextg
追上了Nexti
,意味着所有缓冲区都处于"空白"状态。 -
读取进程必须 等待;
-
一直到写入进程填充了至少一个缓冲区(变为装满),才能继续读。
缓冲池(Buffer Pool)

三种缓冲区:空闲、输入数据、输出数据
空闲:缓冲区内容无效,可分配使用
输入数据:缓冲区中已经有来自外设的新数据,等待处理
输出数据:缓冲区中装有主机准备好、等待发送给外设的数据
三个队列:空缓冲队列、输入队列、输出队列
四种工作方式:收容输入、提取输入、收容输出、提取输出
收容输入:外设将数据写入一个空闲缓冲区后,该缓冲区被放入"输入队列"中
提取输入:主机从"输入队列"中取出一个缓冲区的数据进行处理
收容输出:主机将要发送的数据写入空闲缓冲区,然后将该缓冲区放入"输出队列"
提取输出:外设从"输出队列"中取出数据并完成发送后,将缓冲区还回"空缓冲队列"
I/O 软件
I/O软件总体目标
- 确保I/O设备与CPU并发,提高资源利用率
- 提供简单抽象、清晰、统一接口,统一标准,规范操作
I/O软件的设计目标和原则
- 与具体设备无关
- 统一命名
- 对错误的处理
- 缓冲技术
- 设备的分配和释放
- I/O控制方式
目前在I/O软件中已普遍采用了层次式结构
通常把I/O 软件组织成四个层次:
- 用户层软件
- 设备独立性软件
- 设备驱动程序
- 中断处理程序

设备分配
数据结构:设备控制表 (DCT)

控制器控制表COCT、通道控制表CHCT、系统设备表SDT

SPOOLing技术
该技术是对脱机输入、输出系统的模拟 ,必须建立在具有多道程序功能的操作系统上,还有高速随机外存的支持,通常采用磁盘存储技术
(脱机的意思:外围设备的操作不需要主机参与,主机与设备"脱离",各自独立运行。)
核心思想:使用磁盘(高速外存)作为中间缓冲站,实现外围设备操作和主机操作的解耦,从而让输入/输出操作与程序执行"并行"。
SPOOLing系统

SPOOLing系统的特点
- 提高了I/O的速度
- 将独占设备改造为共享设备:在输入井或输出井中为进程分配一个存储区和建立一张I/O请求表
- 实现了虚拟设备功能:多个进程同时使用一台独占设备,但每个进程都会认为自己独占一个设备,只是该设备是逻辑上的设备
磁盘存储器管理
磁盘结构

磁盘的组成
磁盘由多个盘片组成
每个盘片分两个盘面
每个盘面分若干个磁道(同心圆)
每个磁道分若干个扇区
磁盘的寻址
磁头(盘面)------柱面(磁道)------扇区
磁头Head:第几个盘片的正面或背面
柱面Cylinder:第几个磁道
扇区Sector:磁道上的分区号
扇区数据结构

磁盘类型
固定 头磁盘,每条磁道都有一读/写磁头 ,所有的磁头装在一刚性磁臂中。磁头并行读/写,I/O速度快 ,用于大容量磁盘
移动 头磁盘,每个盘面仅配有一个磁头 ,磁头能移动进行寻道。/O速度较慢 ,结构简单,广泛应用于中小型磁盘设备
磁盘访问时间
寻道时间Ts:磁头移动到指定磁道上的时间
- 启动磁臂时间s与磁头移动n条磁道花费的时间之和 Ts=m×n+s
- m是常数,与磁盘驱动器的速度有关,一般磁盘m=0.2;高速磁盘,m≤0.1
- 磁臂的启动时间s约为2 ms
- 一般寻道时间5~30 ms
旋转延迟时间Tτ :扇区移动到磁头下面的时间
- 5400转硬盘,即5400 r/min,每转需时11.1 ms,平均旋转延迟时间Tτ为5.55 ms
- 对于软盘,其旋转速度为300 r/min或600 r/min, 平均Tτ为50~100 ms
传输时间Tt:数据从磁盘读出或向磁盘写入数据
- 与每次所读/写的字节数b和旋转速度有关
- r为磁盘每秒钟的转数;N为一条磁道上的字节

每秒能传输的字节数为:传输速率 = r * N (单位:字节/秒)
传输b字节要多久:时间 = 数据量 / 传输速率
- 当一次读/写的字节数相当于半条磁道上的字节数时,总时间:

磁盘访问数据时,会经历三个阶段:
(1)寻道时间 Ts:
磁头从当前磁道移动到目标磁道。
(2)旋转延迟时间 Tr=1/(2r):
虽然磁头到了目标轨道,但需要等扇区旋转过来,平均等半圈。
(3)传输时间 Tt=b/(rN):
扇区到了,开始读写数据。数据读写的速率与每圈的字节数和速度有关。
提高磁盘I/O速度的方法
- 提升磁盘硬件性能
- 采用好的调度算法
- 设置磁盘高速缓冲区
磁盘调度
- 磁盘属于共享设备,允许多个进程访问,因此需要磁盘调度算法
- 磁盘调度算法目标是平均寻道时间Ts少
调度算法
先来先服务
FCFS(First-Come, First Served)
优点:简单,每个请求按照时间顺序来处理
缺点:平均寻道距离较大

最短寻道时间优先
最短寻道时间优先SSTF(Shortest Seek Time First)
优点:平均寻道时间较短
缺点: "饥饿"现象,即某些进程长期得不到访问; "磁臂粘着"现象,磁头可能长期停留在同一磁道

扫描
扫描算法, SCAN,又称为电梯调度算法
- 针对最短寻道优先的"饥饿"现象进行改进
- 最短寻道优先+磁头移动方向
- 依据磁头移动方向 访问当前磁道最近的目标磁道
- 优点:不会出现"饥饿"现象,平均寻道时间较短
- 缺点: "磁臂粘着"现象仍未解决;与当前磁道距离近但磁头移动反方向的磁道等待时间长

循环扫描
循环扫描算法, CSCAN
- 到达最外磁道后,返回最内磁道开始扫描算法
- 磁头移动方向固定不变,不会中途折返
- 优点:不会出现"饥饿"现象,平均寻道时间较短,最长等待时间比扫描算法少一半
- 缺点: "磁臂粘着"现象仍未解决,磁头可能长期停留在同一磁道

练习题
有一磁盘管理系统,磁道按内往外方向升序编号,假设当前等待访问磁盘的请求序列为:15、10、30、 150、 190、 80、 95、 40、 140、 20。当前磁头停在90号磁道服务,之前刚完成93号磁道的访问。请分别采用FCFS、SSTF、SCAN、CSCAN算法,求出各种算法的调度序列以及平均寻道距离。
N-Step-SCAN算法
N-Step-SCAN = "每 N 个请求为一组,逐组使用 SCAN 扫描"
- 为了解决 "磁臂粘着"现象
磁臂粘着(Arm Stickiness) 指的是:
当磁盘调度算法(如 SCAN)正在朝一个方向移动磁头时,新来的 I/O 请求总是插入到这个方向的请求队列中,结果磁臂总是在这段磁道范围来回移动,无法完成整个方向的扫描 ,导致其它方向的请求长时间得不到服务。
- 将请求序列划分为多个子序列,新请求只能进入后面的子序列,不能进入当前子序列,避免粘着现象
FSCAN算法
- N-Step-SCAN算法的简化版 只划分两个子序列,一个当前序列,一个后备序
- 当前处理队列是固定的,调度过程中不接受新请求;
- 新来的请求全部放入后备队列;
- 当前队列处理完后,再将后备队列作为新的当前队列,继续处理。
磁盘高速缓存(Disk Cache)
- 利用内存中的存储空间,来暂存从磁盘中读出的一系列盘块中的信息。
- 高速缓存是一组在逻辑上属于磁盘, 而物理上是驻留在内存中的盘块。
高速缓存在内存中的两种形式
- 内存中开辟单独的存储空间作为磁盘高速缓存,其大小是固定的,不受应用程序多少的影响
- 把所有未利用的内存空间变为一个缓冲池,供请求分页系统和磁盘高速缓存共享
提高磁盘速度的其它方法
- 提前读:根据局部性原理,将邻近的磁盘块提前读入内存,例如预调页策略
- 延迟写:修改过的页面不立刻写回磁盘,积累一定数量一次性写回,减少I/O操作次数
- 优化物理块分布:同一文件的物理快尽量集中
- 虚拟盘:利用内存空间或其他存储介质仿真磁盘,例如内存式硬盘和固态硬盘
RAID,磁盘冗余阵列
(1)RAID 0:双硬盘
数据分布在不同磁盘上,并行读写,读写速度快,一旦一个磁盘损坏,数据全部丢失
(2)RAID 1:磁盘镜像
数据重复保存在两个硬盘上,读写速度与单个硬盘相同,但是提供数据备份,安全级别高,磁盘空间浪费
(3)RAID 2-6:带校验
(4)RAID 7:一种新的RAID标准,自身带有智能化实时操作系统和用于存储管理的软件工具,可以看作是一种存储计算机(Storage Computer)
(5)RAID10, RAID53: RAID的组合
两块120GB的硬盘,将两块硬盘的前60GB组成120GB程序应用区,剩下两个60GB组成数据备份区:
- 前120G安装RAID 0,用于程序运行
- 后60G安装RAID 1,用于数据备份
- 前120G如果发生损坏,只需重新安装软件
- 后60G如果发生损坏,可以提供数据备份