十四、输入输出和磁盘调度(二)
9.4 I/O缓冲
- 缓冲的原因
- 进程必须要等待I/O操作完成才能继续(执行速度慢)
- 执行I/O操作期间一些页面必须保留在主存(影响操作系统的交换决策)
- 缓冲技术可以提高外设利用率,尽可能使外设处于忙状态
- 限制:进程的I/O请求不能超过外设的处理能力
- 缓冲区位置:内存、控制器或外设————多级缓冲机制
9.4.1 I/O缓冲
- 面向块的设备
- 信息保存在固定大小的块中
- 传送必须以块为单位
- 如磁盘、U盘
- 面向流的设备
- 信息以字节流的形式传送
- 如终端、打印机、通信端口、鼠标以及多数的其他非辅存设备
- 单方向缓冲
- 单缓冲
- 双缓冲
- 环形缓冲
- 双方向缓冲
- 缓冲池
![image]()
- 缓冲池
9.4.2 单缓冲
- OS为一个I/O请求在内存分配一个缓冲区
- 面向块
- 输入传送到缓冲区
- 需要时缓冲区中的块被移到用户空间
- 再移入另外一块到缓冲区————预读
- 面向流
- 每次传送一行/字节(缓冲区用来保存一行/字节的输入输出)
- 用户每次输入一行/字节,并以回车表示一行/字节的结束
- 到终端的输出一次一行/字节
9.4.3 双缓冲
- 使用两个而不是一个系统缓冲区
- OS清空或填充另一个缓冲区时,进程可以传送数据到另外一个缓冲区(或从另外一个缓冲区读数据)
9.4.4 循环缓冲
- 使用超过两个的缓冲
- 每个缓冲区是循环缓冲的一个单元、
- 提升I/O操作性能(可能爆发式地执行大量I/O)
- 有限缓冲区的生产者/消费者模型
9.4.5 缓冲池
- 缓冲区队列
- 空闲缓冲区
- 输入缓冲区
- 输出缓冲区
- 操作
- 设备输入、CPU读入、CPU写出、设备输出
- 这些操作互斥访问各个缓冲区队列
- 缓冲区整体利用率高
![image]()
9.5 磁盘调度
9.5.1 磁盘硬件

- 磁盘的物理结构
- 磁盘是将若干个涂有铁磁的圆形金属或塑料片组合在一起构成的盘组,每个圆盘有上下两个盘面
- 每个盘面有一个读写磁头,读写磁盘时,磁头通过存取臂在盘面上移动,而盘体绕中心轴高速旋转
- 磁盘旋转一周,相对固定的磁头在盘面上移动轨迹称为磁道(一个圆)
- 各个磁面上半径相同的磁道构成一个柱面
- 一个磁道又被分成多个扇区,一般每条磁道上扇区的数目在8到32之间,每个扇区的字节数相同(512或者4096)
![image]()
- 读写一个磁盘块
- 寻道/移臂(将存储臂移动到相应柱面上)
- 旋转(等待相应扇区旋转到磁头下)
- 实际传输
- 寻道时间占一次磁盘读写的大部分
- 磁盘的一个重要特性:控制器是否支持重叠寻道,即是否可以同时控制两个或多个存取臂驱动器同时进行寻道
9.5.2 磁盘调度
- 寻道时间是影响磁盘性能的最主要因素
![image]()
- 当一个磁盘有多个I/O请求时,可按一定的调度算法对这些请求的服务顺序进行调整,以减少平均寻道时间
- 同时遵循公平原则
9.5.3 磁盘调度算法:先进先出
- 先进先出(FIFO)
- 按访问请求到达的先后次序服务
- 简单、公平
- 一般效率不高,多个进程时性能接近随机调度
- 相邻两次请求可能会造成最内到最外的柱面寻道,使磁头反复移动,增加了服务时间,对机械也不利
- 示例
- 假设磁头的初始位置是100,磁盘访问请求柱面序列:55,58,39,18,90,160,150,38,184
![image]()
- 假设磁头的初始位置是100,磁盘访问请求柱面序列:55,58,39,18,90,160,150,38,184
- 磁头移动的总距离(道数):
- 45+3+19+21+72+70+10+112+146=498
- 平均寻道长度:498/9 = 55.33
9.5.4 磁盘调度算法:优先级
- 优先级(PRI)
- 主要目标并非优化磁盘效率
- 短作业可能具有较高优先级,从而提供较小的交互响应时间
- 长作业可能要等待过长时间
9.5.6 磁盘调度算法:后进先出
- 后进先出(LIFO)
- 有利于事务处理系统
- 设备被分配给最近的使用者,因此移臂幅度可能非常小(局部性原理)
- 可能产生饿死(作业可能永远都不会到达队列头)
- 有利于事务处理系统
9.5.7 磁盘调度算法:最短服务时间优先
- 最短服务时间优先(SSTF)
- 优先选择距离当前磁头最近的访问请求进行服务,主要考虑寻道优先
- 改善了磁盘的平均服务时间
- 可能造成某些访问请求长期等待得不到服务
- 案例分析
- 磁头初始位置:100
- 访问序列:55、58、39、18、90、160、150、38、184
- 顺序:90、58、55、39、38、18、90、150、160、184
![image]()
- 磁头移动总距离(道数):10+32+3+16+1+20+132+10+24=248
- 平均寻道长度:248/9 = 27.55
9.5.8 磁盘调度算法:扫描算法
- 电梯算法/扫描算法(SCAN)
- 设备无访问请求时,磁头不动
- 有访问请求时,磁头按一个方向移动,在移动过程中对遇到的访问请求进行服务,然后判断该方向上是否还有访问请求,如果有则继续扫描;否则改变移动方向,并为经过的访问请求服务,如此反复
- 克服了最短服务时间优先(请求可能会长期等待)的缺点
- 存在偏爱靠内&外道的缺点
- 案例分析
- 磁头初始位置:100
- 访问序列:55、58、39、18、90、160、150、38、184
- 顺序:150、160、184、90、58、55、39、38、18(假设原方向是磁道递增方向)
![image]()
- 磁头移动总距离:50+10+24+94+32+3+16+1+20=250
- 平均寻道长度:250/9 = 27.78
9.5.9 磁盘调度算法:单向扫描算法
- 单向扫描算法(C-SCAN)
- 从有读写请求的最低编号柱面开始递增扫描,途中按照柱面次序处理访问请求;处理完最高编号柱面上的请求后,存取臂立即带动读写磁头快速返回到有读写请求的最低编号柱面,返回时不处理任何访问请求;返回后可再次递增扫描
- 克服了SCAN偏爱靠里、外服务的缺点
- 中负载或者重负载时性能比扫描算法好
- 案例分析
- 磁头初始位置:100
- 访问序列:55、58、39、18、90、160、150、38、184
- 顺序:150、160、184、18、38、39、55、58、90(假设原方向是磁道递增方向)
![image]()
- 磁头移动总距离(道数):50+10+24+166+20+1+16+3+32=322
- 平均寻道长度:322/9 = 35.78
9.5.10 磁盘调度算法:N步扫描法
- N步扫描法(N-step-SCAN)
- 将磁道请求队列分为若干个长度为N的子队列
- 每一次SCAN处理一个队列
- 新来的请求必须加入到没在处理的队列中
- 克服了SCAN偏爱最近作业(磁头臂粘性)的缺点
- 特例:FSCAN
- 两个队列
- 开始时所有请求在一个队列中,另一个队列用来添加新请求
9.6 RAID
- RAID(独立、廉价磁盘冗余阵列)
![image]()
- 分为七个级别(RAID 0至6)
- 一般特点:
- 把多个物理磁盘组织在一起,作为一个逻辑驱动器-->提供磁盘跨越功能
- 数据分为多个数据块,分布在阵列的各个物理磁盘上-->可以并行写入/读出多个磁盘,提高磁盘的访问速度
- 利用磁盘冗余可进行镜像或校验操作等-->提高意外恢复能力
- 整个逻辑盘的数据被分散分布(通过阵列管理软件)在多个(至少两个)物理盘上,并行读写
- 没有冗余能力
![image]()
- 注:strip可以是物理块、扇区或其他单位
9.6.1 RAID 1
- 把一个磁盘的数据镜像到另一个磁盘上,可从任意磁盘读数据,数据同时更新到两个磁盘
- 两个盘上实施,没有冗余,数据安全性更好
- 磁盘利用率最低(50%)
9.6.2 RAID 2
- 并行读写:所有磁盘都参与每一次I/O请求(所有磁头任何时刻都处于同一位置)
- 通过汉明码(一位纠错,两位检错)实现数据冗余(需要的磁盘数少于RAID 1)
- 仅用于错误率高的环境中(不太实用)
![image]()
9.6.3 RAID 3
- 只采用一个冗余磁盘存储校验数据
- 校验数据:$ P(b) = b_0 \oplus b_1 \oplus b_2 \oplus b_3 $
- 丢失数据可以从校验数据及其他数据恢复:$ b_1 = b_0 \oplus P(b) \oplus b_2 \oplus b_3 $
- 数据速率高,但同时只能处理一个 I/O 请求
![image]()
9.6.4 RAID 4
- 独立读写:阵列中每个磁盘的存取各自独立进行,从而可同时处理多个I/O请求
- 校验基于数据块进行(假设更新数据B1)
![image]()
![image]()
9.6.5 RAID 5
- 类似 RAID 4,但校验数据分布在各个磁盘上
- 可避免 RAID 4中可能出现的瓶颈————校验磁盘
![image]()
9.6.6 RAID 6
- 可以采用两种不同的数据校验方法
- 可以处理有两个磁盘出错的情形
- 数据可靠性极高
- 写性能损失严重
![image]()
9.6.7 RAID级别的比较

9.7 磁盘高速缓存
- 磁盘缓存:内存中的磁盘缓冲区,是磁盘中某些扇区的副本
- 处理一个请求
- 若数据在cache中,则不需要磁盘数据传输,从cache传送给调用程序(复制或使用共享存储空间)
- 若数据不在cache中,则从磁盘读并添加到cache中
9.7.1 磁盘缓冲替换算法
- 替换策略
- LRU(最近最少使用):替换cache中未被访问的时间最长的块,最常用
- cache是一个栈,最近访问过的块在栈顶(通过栈指针实现块的移动)
- LFU(最不常用):替换被访问次数最少的块
- cache中的每个块关联一个计数器,替换计数器最小的块
- 坏置换算法(局部性原理)
- 基于频率的替换算法及其改进
- LRU(最近最少使用):替换cache中未被访问的时间最长的块,最常用
- 磁盘访问的特征————密集型/集中性
- 可能有些块在短期内被访问很多次,而之后则再也用不着,则计数器的变化就不能反映当前的引用情况
- 需要考虑磁盘访问的这种密集特征,对密集引用计数————基于频率的替换
- LRU算法
- LFU算法
- 基于频率的替换
9.7.2 基于频率的替换
- 第一个版本
- 把LRU算法中的特殊栈分成两部分:新区、老区
- 每个块增加一个引用计数器,其中,新加进来的块计数器 count = 1
- cache命中:把对应的块移到新区前端;若原来在新区,则计数器不变;若原来在老区,则count加1
- cache失误:替换老区中count最小的块
- 第一个版本存在的问题:
- 一个短期内频繁访问的块留在新区内,则count一直是1
- 转到老区后,这个块将很快被替换掉
![image]()
- 第二个版本
- 使用三个区:新区、中间区、老区
- 块的年龄变化:新区-->中间区-->老区
- 中间区避免新读入的缓存块在第一次出新区域时马上被置换,有一个过渡期
![image]()
- 中间区避免新读入的缓存块在第一次出新区域时马上被置换,有一个过渡期
9.7.3 RAM盘
- RAM(随机存取存储器)盘即是用一部分内存模拟的磁盘
- 具有立即存取的优点,对于频繁读取磁盘的应用程序以及文件(如字库文件、图形图像程序文件、字处理程序等),将信息存储在RAM盘上能起到加速工作的效果
- 例如,在config.sys中设置RAM盘
- 如:DEVICE=C:\DOS\RAMDRIVE.sys/E1024
- 为了提高RAM盘的使用效率,可以改变一个环境变量TEMP,将它设为RAM的目录
- RAM盘存在于内存之中,使用中注意存盘



















浙公网安备 33010602011771号