考研学习
知识点讲义操作系统

第 5 章 输入/输出管理

408 操作系统第 5 章 输入/输出管理复习讲义,涵盖核心概念、重点考点与典型题型。

Last updated on

一、第 5 章到底在研究什么?

前几章分别解决了:

  • 进程如何使用 CPU;
  • 进程之间如何同步;
  • 程序如何使用内存;
  • 文件如何组织和存储。

而第 5 章解决的是:

程序想和外部世界交换数据时,操作系统究竟怎么把“用户的一次 read/write”变成真正的硬件 I/O?

例如程序执行:

scanf("%c", &d);

表面看起来只是“从键盘读一个字符”,实际上会经历:

用户程序
   ↓
C 标准库
   ↓
read 系统调用
   ↓
设备独立性软件
   ↓
键盘驱动程序
   ↓
设备控制器
   ↓
键盘硬件
   ↓
中断
   ↓
中断处理程序
   ↓
内核缓冲区
   ↓
用户缓冲区
   ↓
变量 d

所以这一章的主线其实非常清楚:

应用程序 → 操作系统 → 驱动程序 → 设备控制器 → 物理设备

然后再研究三个问题:

如何降低 CPU 管 I/O 的负担?

→ 轮询、中断、DMA、通道。

多个进程怎么共享设备?

→ 缓冲、设备分配、设备独立性、SPOOLing。

外存特别是磁盘怎么高效访问?

→ 磁盘调度、旋转优化、SSD。

二、5.1 I/O 管理概述

1. I/O 设备分类

I/O 设备就是负责计算机和外界交换数据的设备。资料按照多个维度分类,其中考试最重要的是 块设备与字符设备。

类型信息交换单位能否寻址典型设备常用控制方式
字符设备字符/字节通常不能随机寻址键盘、鼠标、打印机中断
块设备数据块可以磁盘DMA

理解这一区别非常重要。

磁盘为什么是块设备?

因为它不是“给我下一个字节”这么访问,而是:

读取第 1024 个块
读取第 11408 个扇区

所以可以随机定位。

而键盘的输入本质是:

a
b
c
...

字符一个接一个到达,不能说:

“把键盘历史上的第 500 个字符随机访问一下。”

因此属于字符设备。

从共享属性看还可以分成:

类型含义例子
独占设备同一时期只能一个进程使用打印机
共享设备多个进程可以逻辑共享磁盘
虚拟设备把独占设备虚拟成共享设备SPOOLing 后的打印机

这里以后会和 SPOOLing 联系起来。

三、I/O 接口和设备控制器

这是一个容易混乱的地方。

物理设备通常不能直接理解 CPU 的指令。例如 CPU 不可能直接对打印机机械部件说:

打印字符 A

中间需要一个硬件:

设备控制器(I/O 接口)

它相当于 CPU 和外设之间的翻译器。

其结构大致是:

CPU
 │
 │ 数据线 / 地址线 / 控制线
 ↓
设备控制器
 ├─ CPU 接口
 ├─ I/O 逻辑
 └─ 设备接口
       ↓
     I/O设备

设备控制器要完成命令识别、数据交换、状态报告、地址识别、缓冲、差错控制等工作。

I/O 端口

CPU 真正访问设备控制器时,访问的是控制器内部的寄存器,也称 I/O 端口。

最重要的是三个:

寄存器作用
数据寄存器存放正在输入或输出的数据
状态寄存器记录设备忙、空闲、完成、错误等状态
控制寄存器CPU 写入命令,控制设备工作

例如 CPU 想读键盘:

CPU
 ↓
检查状态寄存器
 ↓
发现 ready=1
 ↓
读取数据寄存器
 ↓
得到字符

四、I/O 端口的两种编址方式

这是计组和操作系统都会考的交叉知识点。

1. 独立编址

也叫:

I/O 映射方式。

内存地址空间与 I/O 端口地址空间分开。

例如:

内存地址:
0x00000000 ~ 0xFFFFFFFF

I/O端口:
0 ~ 65535

CPU 访问内存:

MOV

访问 I/O:

IN
OUT

也就是说:

访问设备有专门指令。

2. 统一编址

也叫:

内存映射 I/O,Memory Mapped I/O。

把一部分内存地址直接映射成 I/O 寄存器。

例如:

0x00000000 ~ 0xEFFFFFFF → 内存
0xF0000000 ~ 0xFFFFFFFF → I/O设备

于是 CPU 可以直接:

LOAD
STORE

操作设备。

优点是编程简单、可以直接利用普通访存指令;缺点是会占用一部分内存地址空间。

五、★★★★★ 高频核心:四种 I/O 控制方式

这是整章最重要的知识之一。

四种方式的发展逻辑只有一句话:

让 CPU 越来越少管 I/O。

顺序是:

程序直接控制
       ↓
中断驱动
       ↓
DMA
       ↓
通道

可以理解成:

CPU全程亲自干
      ↓
设备做好后通知CPU
      ↓
找DMA秘书帮CPU搬整块数据
      ↓
找通道处理机自己执行整个I/O程序

资料也明确指出,I/O 控制方式的发展宗旨就是减少 CPU 对 I/O 的干预。

六、程序直接控制方式——轮询

又称:

程序查询方式、程序轮询方式。

其基本过程:

CPU 发出读命令
     ↓
CPU 查询设备状态
     ↓
没好?
     ↓
继续查询
     ↓
继续查询
     ↓
ready
     ↓
CPU 从设备控制器读取一个字
     ↓
CPU 写入内存

伪代码相当于:

while (status != READY)
    ;

data = device_register;
memory[x] = data;

最大的问题就是:

忙等待。

比如键盘一秒后才有数据。

CPU 每纳秒都在问:

好了吗?
好了吗?
好了吗?
好了吗?
……

CPU 和设备基本串行工作。

因此 CPU 利用率很低。

七、中断驱动方式

解决轮询问题的方法很自然:

不让 CPU 一直问,而让设备完成后主动通知 CPU。

过程:

CPU
 ↓
启动I/O
 ↓
I/O进程阻塞
 ↓
CPU运行其他进程
 ↓
设备执行I/O
 ↓
设备完成
 ↓
产生中断
 ↓
CPU执行中断处理程序
 ↓
取出数据
 ↓
唤醒原进程

假设进程 P:

P运行
 │
 │ read()
 ↓
P阻塞
 │
 ├──────── CPU运行Q
 │
设备工作
 │
设备完成
 ↓
中断
 ↓
中断处理
 ↓
P:阻塞 → 就绪

注意一个非常常考的细节:

设备完成产生中断时,原来的 I/O 请求进程通常仍然处于阻塞态。

是中断处理程序处理完成后把它:

阻塞 → 就绪

不是:

阻塞 → 运行

因为它还得等待 CPU 调度。

资料中特别把这一点标为 2017、2023 年考点。

八、中断方式为什么还不够好?

虽然 CPU 不再忙等,但还有两个问题。

第一:

数据仍然要经过 CPU 寄存器。

数据路径:

设备
 ↓
设备控制器
 ↓
CPU寄存器
 ↓
内存

第二:

CPU 往往以字或字节为单位干预。

假如一次磁盘传输:

4 KB

如果每传一个字节都中断一次:

4096 次 CPU 干预

显然不划算。

因此需要 DMA。

九、★★★★★ DMA 方式

DMA:

Direct Memory Access,直接存储器存取。

核心思想:

设备和内存直接交换数据,不再经过 CPU 寄存器。

原来:

设备 → CPU → 内存

DMA:

设备 ←→ DMA控制器 ←→ 内存
                 ↑
            CPU只负责初始化

DMA 有三个非常重要的特征:

项目DMA
基本传输单位数据块
数据路径设备 ↔ 内存
CPU 干预一块数据开始和结束时

十、DMA 控制器四个重要寄存器

这个经常直接出选择题。

寄存器含义
CR命令/状态
MAR主存地址
DR数据
DC数据计数

其中最重要的是:

MAR:数据放哪里
DC:传多少

例如:

把磁盘的一块 4096B 数据
传到内存 0x100000

CPU 可以设置:

MAR = 0x100000
DC = 4096

然后:

启动 DMA

CPU 就去做其他事情。

DMA 自己搬:

磁盘 → 内存

完成后:

DMA → 中断CPU

所以 CPU 的工作大致只有:

设置参数
↓
启动 DMA
↓
干别的
↓
接收完成中断

十一、DMA 和中断最容易混淆的地方

两者都用了中断。

区别并不是:

“中断方式有中断,DMA 没有中断。”

这是错的。

DMA 完成后照样通过中断通知 CPU。

真正区别在数据传输本身。

项目中断 I/ODMA
传输单位字/字节块
数据是否经过 CPU是否
CPU 干预频率高低
适合中低速设备高速块设备
完成通知中断中断

因此可以记:

中断解决“CPU 等不等”;DMA 进一步解决“CPU 搬不搬”。

十二、通道控制方式

通道可以理解为:

一个专门负责 I/O 的小型处理机。

CPU 不再连 DMA 的具体参数都事事操心,而是把一段:

通道程序

交给通道。

流程变成:

CPU
 ↓
告诉通道:
设备是谁
通道程序在哪里
 ↓
CPU继续工作
 ↓
通道执行通道程序
 ↓
通道控制多个I/O设备
 ↓
全部完成
 ↓
中断CPU

通道比 DMA 更自主。

资料中的区别非常重要:

DMA通道
CPU 预设内存地址、大小等参数通道通过程序自主执行
通常负责一次块传输可以完成一系列 I/O 操作
通常对应设备范围较小可管理多台设备
本质是专用硬件控制器本质更接近 I/O 专用处理机

考研主线记成:

轮询:
CPU 等 + CPU 搬

中断:
CPU 不等 + CPU 搬

DMA:
CPU 不等 + CPU 不搬数据块

通道:
CPU 连复杂的 I/O 控制过程都交出去

这张关系一定要彻底理解。

十三、★★★★★ I/O 软件的层次结构

资料把 I/O 软件分成四层:

用户层软件
      ↓
设备独立性软件
      ↓
设备驱动程序
      ↓
中断处理程序
      ↓
硬件

这是 2011、2012、2013 年等真题涉及过的高频结构。

用户层软件

离用户最近。

例如:

printf()
scanf()
fread()
fwrite()

这些库函数本身位于用户层。

最终通常会触发系统调用:

read
write

设备独立性软件

也叫:

设备无关软件。

核心思想:

上层程序不用知道具体是什么硬件。

例如应用程序写:

write(fd, buf, 100);

应用程序不需要知道下面到底是:

机械硬盘
SSD
USB盘
网络设备
打印机

设备独立层负责完成统一命名、保护、设备分配与回收、逻辑设备到物理设备映射、缓冲、差错控制等公共工作。

设备驱动程序

这是:

真正理解具体硬件的人。

例如通用层只知道:

read block 100

磁盘驱动可能把它转换成:

设置设备控制器寄存器
设置DMA
启动磁盘
等待完成

所以:

设备驱动程序具有强烈的设备相关性。

不同类型硬件通常需要不同驱动。

资料把设备驱动程序的功能列为 2025 年考点。

中断处理程序

最靠近硬件。

当设备完成:

设备控制器
     ↓
    中断
     ↓
CPU
     ↓
中断处理程序

中断程序处理设备状态、错误、数据以及进程唤醒等。

十四、用一次 write 理解整个层次

假设用户:

write(fd, buf, 100);

可以这样理解:

① 用户程序
write(fd,buf,100)

        ↓

② 用户层 I/O 软件
调用系统调用

        ↓

③ 陷阱进入内核

        ↓

④ 设备独立性软件
检查参数
找到逻辑设备
分配设备
缓冲管理

        ↓

⑤ 驱动程序
转换成设备具体命令

        ↓

⑥ 设备控制器
真正执行

        ↓

⑦ I/O完成

        ↓

⑧ 中断

        ↓

⑨ 中断处理程序
确认完成
唤醒进程

资料把这种完整 I/O 请求链路作为重点示例解释。

十五、应用程序 I/O 接口

考纲中特别加入了字符设备、块设备、网络设备接口以及阻塞/非阻塞 I/O。

字符设备接口

典型:

键盘
打印机
串口

常见操作:

get
put

只能顺序进行字符输入输出。

块设备接口

典型:

磁盘

常见操作:

read
write
seek

其中 seek 用来改变下一次读写位置。

操作系统通常把复杂的:

柱面号
盘面号
扇区号

隐藏起来,对上层呈现:

逻辑块0
逻辑块1
逻辑块2
...

网络设备接口

通常采用:

Socket(套接字)。

应用程序:

socket
 ↓
连接另一台计算机
 ↓
send / recv

因此网络设备不像普通磁盘那样简单地用一个块设备接口解决。

十六、阻塞 I/O 与非阻塞 I/O

阻塞 I/O

假设:

read(fd, buf, 100);

数据还没来。

进程:

运行
 ↓
read
 ↓
阻塞
 ↓
I/O完成
 ↓
就绪
 ↓
调度
 ↓
运行

也就是说:

I/O 没完成,我就不继续运行。

非阻塞 I/O

调用:

read(...)

如果没有数据:

立即返回“暂无数据”

进程继续执行。

过一会:

再 read

所以:

请求
 ↓
没数据
 ↓
立即返回
 ↓
做其他事
 ↓
再试

这有点像轮询。

资料强调其优点是进程等待期间仍可以执行其他任务,但如果不断主动轮询,也会浪费 CPU。

十七、★★★★★ 缓冲技术

缓冲区通常在:

内存

中开辟。

为什么需要缓冲?

本质是:

CPU:很快
设备:很慢

如果直接配合:

CPU → 等设备 → CPU → 等设备

效率很差。

加入 Buffer:

设备 → Buffer → CPU

双方就能部分并行。

资料总结缓冲区有四个主要作用:缓解速度不匹配、减少中断频率、解决数据粒度不匹配、提高 CPU 与 I/O 的并行性。

十八、★★★★★ 单缓冲计算

这是本章非常典型的计算题。

设:

T = 设备把一块数据输入缓冲区的时间
M = 缓冲区 → 用户工作区的传送时间
C = CPU处理一块数据的时间

单缓冲结构:

设备 → Buffer → 用户工作区 → CPU处理

关键问题:

哪些阶段能够并行?

单缓冲下:

设备输入下一块数据 T

可以和:

CPU处理上一块数据 C

并行。

但:

Buffer → 工作区的 M

会形成额外开销。

稳定状态下每块耗时:

例如:

则:

因为设备更慢。

如果:

则:

此时 CPU 处理更慢。

十九、★★★★★ 双缓冲

两个缓冲区:

       ┌→ Buffer1 ─┐
设备 ──┤            ├→ CPU
       └→ Buffer2 ─┘

当 CPU 正在处理 Buffer1 时:

设备可以往 Buffer2 写

处理 Buffer2 时:

设备又往 Buffer1 写

因此:

T

可以与:

M+C

整体重叠。

所以每块数据的稳定处理时间:

注意和单缓冲区别:

这两个公式非常值得直接记住,但做题最好理解时间重叠关系,而不是只背公式。

二十、循环缓冲与缓冲池

如果只有两个缓冲区仍不够:

Buffer1
Buffer2
Buffer3
...

可以组成循环缓冲。

进一步,操作系统把大量缓冲区统一管理,就形成:

缓冲池。

资料中的缓冲池通常有三种队列:

空缓冲队列
输入队列
输出队列

而一个缓冲区在不同时间可以作为:

收容输入 hin
提取输入 sin
收容输出 hout
提取输出 sout

工作流程可以理解成一个“容器循环使用系统”:

空缓冲
 ↓
装入输入数据
 ↓
输入队列
 ↓
CPU取走数据
 ↓
空缓冲

输出方向类似。

二十一、Buffer 和 Cache 不要混

这是典型易错点。

项目BufferCache
中文缓冲区高速缓存
解决什么速度不匹配、并行避免重复访问低速设备
数据性质中间暂存低速设备数据的副本
是否一定以后还用不一定利用局部性,希望再次命中

例如:

磁盘 → 内存 → CPU

缓冲:

“磁盘太慢,先放这里慢慢交接。”

缓存:

“这个磁盘块最近可能还会读,先留一份在内存里。”

资料特别指出,磁盘高速缓存虽然叫 cache,但其物理位置仍然在主存,不是 CPU 和主存之间那个 Cache。

二十二、★★★★★ 设备分配与回收

多个进程同时请求设备时,操作系统必须决定:

设备给谁?
什么时候给?
谁在等?
设备属于哪个控制器?
控制器属于哪个通道?

为此建立若干管理表。

核心关系:

系统
 │
SDT
 │
设备
 │
DCT
 │
控制器
 │
COCT
 │
通道
 │
CHCT

DCT

Device Control Table:

设备控制表

每个设备一张。

记录:

设备类型
设备标识
忙/闲
等待队列
所属控制器
...

COCT

Controller Control Table:

控制器控制表。

每个控制器一张。

CHCT

Channel Control Table:

通道控制表。

每个通道一张。

SDT

System Device Table:

系统设备表。

整个系统一张。

相当于:

“全系统设备总目录”。

资料对这套结构有完整说明。

二十三、★★★★★ 设备分配访问顺序

一道模拟题直接考过:

SDT → DCT → COCT → CHCT

原因是先:

全系统找设备

再:

检查具体设备

然后:

检查控制器

最后:

检查通道

所以可以记成:

系统 → 设备 → 控制器 → 通道

即:

SDT
 ↓
DCT
 ↓
COCT
 ↓
CHCT

模拟题对此直接给出了正确顺序。

二十四、设备分配算法

设备也要排队。

最常见的是:

FCFS

谁先申请谁先分配。

还有:

最高优先级优先

高优先级进程先得到设备,相同优先级再 FCFS。

二十五、设备分配和死锁

设备属于资源,因此当然也可能死锁。

资料区分:

安全分配

进程请求一次 I/O 后:

立即阻塞

直到这次 I/O 完成。

它不会一边占着设备 A,一边继续申请 B、C、D。

所以:

不容易形成复杂资源循环等待。

但并行性低。

不安全分配

进程申请设备 A 后继续运行:

A
↓
继续申请B
↓
继续申请C

效率高,但有可能:

P1 占 A 等 B

P2 占 B 等 A

形成死锁。

二十六、★★★★★ 设备独立性

这是一个很重要的思想。

假设程序写死:

把输出写到物理打印机 Printer-03

如果 Printer-03 坏了,程序可能就不能用了。

更好的设计是:

程序:
我要一台“打印机”

至于实际分配:

Printer-01
Printer-02
Printer-03

由 OS 决定。

所以:

逻辑设备名
     ↓
操作系统
     ↓
物理设备名

这种机制叫:

设备独立性。

其好处是程序可移植、设备分配灵活、容易实现 I/O 重定向。

二十七、LUT:逻辑设备表

OS 需要一张表保存:

逻辑设备名
   ↓
物理设备名
   ↓
驱动入口

这就是:

Logical Unit Table,LUT。

例如:

logical_printer
       ↓
Printer-07
       ↓
printer_driver

单用户系统可以整个系统一张 LUT。

多用户系统通常每个用户一张 LUT,从而不同用户可以使用相同逻辑设备名。资料把逻辑设备名到物理设备名映射列为 2009 年考点。

二十八、★★★★★ SPOOLing 假脱机技术

这是本章另一大核心。

先理解打印机问题。

打印机是:

独占设备。

如果 P1 正在打印 100 页:

P1
 ↓
打印机

P2、P3 都必须等待。

效率很差。

SPOOLing 的思想是:

不要把真正的打印机直接分配给用户进程。

而是让用户先把打印内容写入:

磁盘。

因此:

P1 ─┐
P2 ─┼→ 磁盘输出井 → 输出进程 → 打印机
P3 ─┘

对于 P1:

把文件写入磁盘

很快就能完成。

于是 P1 会觉得:

“我已经把打印任务提交成功了。”

至于真正什么时候打印,由后台输出进程安排。

这就是:

把一台物理独占打印机虚拟成多台逻辑打印机。

二十九、SPOOLing 的组成

结构可以记成:

             磁盘
      ┌──────────────┐
输入设备 → 输入井
      │
      │
      │ 输出井 → 输出设备
      └──────────────┘

但数据不能直接从低速设备跳到磁盘,因此还有内存缓冲区:

输入设备
 ↓
输入缓冲区(内存)
 ↓
输入井(磁盘)

输出则:

输出井(磁盘)
 ↓
输出缓冲区(内存)
 ↓
输出设备

同时存在:

输入进程
输出进程

所以 SPOOLing 的典型组成就是:

位置内容
磁盘输入井、输出井
内存输入缓冲区、输出缓冲区
软件输入进程、输出进程

三十、“假脱机”为什么叫假脱机?

早期脱机 I/O 是:

主机 CPU 不直接参与

需要真正的外围处理机。

后来不再使用物理外围机,而是:

磁盘 + 输入输出进程

在软件上模拟这种效果。

所以:

假脱机 = 用软件模拟脱机 I/O。

SPOOLing 的两个核心作用可以概括为:

CPU与I/O并行
+
独占设备虚拟化

最典型的就是:

共享打印机。

三十一、★★★★★ 从 scanf 看完整 I/O 流程

资料专门用:

scanf("%c", &d);

讲了整个流程,这是理解本章最好的例子。

假设用户按下:

A

过程:

用户程序
 ↓
scanf()
 ↓
用户缓冲区没有数据
 ↓
read系统调用
 ↓
trap
 ↓
用户态 → 内核态
 ↓
设备独立性软件
 ↓
键盘驱动
 ↓
启动键盘I/O
 ↓
进程阻塞
 ↓
CPU运行其他进程

然后:

用户按A
 ↓
键盘控制器得到A
 ↓
产生中断
 ↓
CPU进入中断处理程序
 ↓
A:I/O端口 → 内核缓冲区
 ↓
唤醒原进程

之后:

原进程再次调度
 ↓
内核缓冲区
 ↓
用户缓冲区
 ↓
scanf解析
 ↓
变量d='A'

非常重要的数据流:

I/O端口
   ↓
内核缓冲区
   ↓
用户缓冲区

资料明确指出:

I/O 端口 → 内核缓冲区主要由驱动程序完成;内核缓冲区 → 用户缓冲区属于设备无关 I/O 软件处理。

这个例子把:

系统调用
进程阻塞
中断
驱动
缓冲
用户态/内核态

全部串起来了。

三十二、5.3 磁盘结构

这是第 5 章的另一大部分。

一个盘面:

             磁道
       ┌───────────┐
       │ ○ ○ ○ ○   │
       │   ○ ○     │
       └───────────┘

每个磁道进一步分成:

扇区。

多个盘片叠起来:

盘面0 ──────
盘面1 ──────
盘面2 ──────
盘面3 ──────

半径相同的一组磁道叫:

柱面。

所以物理地址一般表示为:

柱面号
+
盘面号
+
扇区号

三十三、磁盘容量计算

如果一个传统磁盘有:

C 个柱面
H 个盘面
S 个扇区/磁道
B 字节/扇区

则容量:

资料强调现代磁盘可能采用 ZBR,即不同区域的磁道扇区数不同;但统考的基础计算题一般会直接给定参数。

三十四、磁盘读取一个块究竟怎么找?

例如地址:

柱面 20
盘面 3
扇区 7

先:

移动磁头臂
20号柱面

再:

选择盘面3对应磁头

最后:

等待扇区7转到磁头下面

所以磁盘访问时间天然分成:

寻道
+
旋转
+
传输

三十五、物理格式化、分区、逻辑格式化

这三个千万不要混。

正确顺序:

物理格式化
    ↓
分区
    ↓
逻辑格式化

物理格式化

也叫:

低级格式化。

主要干什么?

把磁盘表面划分成可被控制器识别的扇区。

一个扇区大致:

头部
数据
尾部
CRC等

分区

把整块磁盘分成:

C:
D:
E:

或不同逻辑分区。

逻辑格式化

也叫:

高级格式化。

作用是:

在分区中建立文件系统。

例如建立:

根目录
空闲空间管理结构
文件系统元数据

所以真题中:

“高级格式化建立文件系统”

是正确的。

资料把物理格式化、逻辑格式化均列为 2017、2021 年考点。

模拟题也直接考过:

高级格式化为指定分区建立文件系统并初始化元数据。

三十六、引导块

电脑开机时:

CPU刚启动

内存里还没有 Windows/Linux 内核。

所以需要:

ROM中的小型引导程序
 ↓
读取磁盘引导块
 ↓
加载完整引导程序
 ↓
找到OS内核
 ↓
把OS装入内存
 ↓
启动OS

传统 MBR 磁盘中:

0号扇区
 ↓
MBR
 ├─ 引导代码
 ├─ 分区表
 └─ 活动分区信息

然后继续找到活动分区的引导扇区。

三十七、坏块

磁盘出现坏扇区后,操作系统不能继续把正常文件放进去。

处理思想有两类。

简单设备:

OS发现坏块
 ↓
在文件系统中标记不可使用

复杂设备:

磁盘控制器发现坏块
 ↓
使用备用扇区
 ↓
重新映射

上层 OS 甚至感觉不到。

三十八、★★★★★ 磁盘访问时间

这是重要计算题。

一次磁盘访问:

其中:

寻道时间

移动磁头到目标磁道。

资料给出的线性估计:

其中 是移动磁道数。

平均旋转延迟

如果转速为 圈/秒:

一圈:

平均等半圈:

例如:

先转换成:

所以:

数据传输时间

如果一条磁道有 字节,需要传输 字节:

因此:

三十九、为什么磁盘调度主要优化寻道时间?

因为机械磁盘最慢的操作之一是:

移动磁头臂。

所以多个磁盘请求:

20
180
25
170
30
160

如果按乱序执行:

磁头左右来回跑

开销很大。

因此磁盘调度算法最主要目标是:

减小平均寻道距离。

四十、★★★★★ FCFS 磁盘调度

先来先服务。

请求队列:

55, 58, 39, 18, 90, 160, 150, 38, 184

初始磁头:

100

访问:

100
 ↓
55
 ↓
58
 ↓
39
 ↓
18
 ↓
90
 ↓
160
 ↓
150
 ↓
38
 ↓
184

总磁头移动量:

资料中的结果为:

平均寻道长度:

优点:

公平、简单。

缺点:

磁头可能疯狂来回运动。

四十一、★★★★★ SSTF

Shortest Seek Time First:

最短寻道时间优先。

每次选择:

距离当前磁头最近的请求。

假设:

磁头 = 100
请求 = 90, 55, 58, ...

第一步肯定:

100 → 90

因为最接近。

然后重新计算离 90 最近的。

思想和 CPU 的 SJF 很像:

每次贪心选当前代价最小的。

性能往往不错。

但有一个非常重要的问题:

饥饿。

如果磁头一直在 50 附近,而:

48
52
49
51
...

不断产生新请求。

远处:

190

可能永远等不到。

资料把 SSTF 的应用列为 2019、2021 年考点。

四十二、★★★★★ SCAN 电梯算法

SCAN 很像电梯。

假设:

当前100
方向:磁道号增大

那么:

100
 ↓
150
 ↓
160
 ↓
184
 ↓
到高端
 ↓
反向
 ↓
90
 ↓
58
 ↓
55
 ↓
39
 ↓
38
 ↓
18

核心规则:

一个方向一直扫,扫完再反向。

因此叫:

电梯算法。

它比 SSTF 更公平,不容易让远处请求长期饥饿。

模拟题也直接考过初始方向对 SCAN 访问序列的影响。

四十三、C-SCAN

Circular SCAN:

循环扫描。

假设只允许:

小磁道 → 大磁道

到最大端后:

直接返回最小端

返回途中:

不提供服务。

然后再次:

小 → 大

所以:

0 → → → → max
↑             │
└─────────────┘

这样做的优势是:

请求等待时间更加均匀。

SCAN 的问题是,中间磁道可能会因为磁头双向经过而获得更多机会。

C-SCAN 将服务方向统一,所以公平性更好。

四十四、LOOK 与 C-LOOK

传统 SCAN:

必须移动到磁盘物理边缘

例如最大请求只有:

184

但磁盘有:

199

SCAN 可能仍走到:

199

再折返。

但:

185~199

根本没请求。

所以 LOOK:

只走到当前方向最远的请求。

然后反向。

C-LOOK 同理。

资料明确指出,LOOK/C-LOOK 是 SCAN/C-SCAN 的改进形式。

四十五、磁盘调度算法怎么做题最快?

看到磁盘调度题,不要凭脑子想象。

先在纸上画:

0 -------------------------------- 199

标:

18 38 39 55 58 90 100 150 160 184

圈出:

当前位置 = 100

再画:

→

表示初始方向。

然后按算法移动。

最后只计算相邻点距离:

平均寻道长度:

尤其 SCAN/C-SCAN:

第一件事永远先看题目有没有给初始方向。

四十六、FCFS / SSTF / SCAN / C-SCAN 总对比

算法核心优点最大问题
FCFS谁先来谁先服务公平简单寻道距离大
SSTF最近者优先平均性能好可能饥饿
SCAN双向电梯公平、性能较好两端等待不够均匀
C-SCAN单方向循环等待更均匀回程有额外移动
LOOK到最远请求即返回少走无效距离本质仍为 SCAN
C-LOOK到最远请求后跳到另一端请求少走无效距离本质仍为 C-SCAN

资料对四种基本算法的优缺点也有相同总结。

四十七、NStepSCAN 和 FSCAN

这部分频率低一些,但资料仍然讲了。

它们主要解决:

磁臂黏着。

例如磁头在 50 附近。

不断有:

49
51
48
52
...

新请求。

那么磁头可能一直被“黏”在这个区域。

NStepSCAN 会把队列分组:

每 N 个请求组成一组

当前只处理当前组。

新请求:

放后面

不能插队。

FSCAN 更直接,只设:

队列 A:当前批次
队列 B:新来的请求

当前扫描期间:

新请求全部进B

处理完 A 后:

A/B交换

这样就不会永远追着新来的请求跑。

四十八、减少旋转延迟:交替编号

假设磁盘:

0 1 2 3 4 5 6 7

CPU 读完扇区 0 后,需要一点时间处理。

此时磁盘还在转。

等 CPU 准备读 1:

1可能已经转过去了

于是要再等一整圈。

解决办法:

交替编号。

例如逻辑上:

0,1,2,3...

物理上可以:

0,4,1,5,2,6,3,7

这样读完 0,CPU 稍微处理后:

1刚好转过来

可以明显减少旋转等待。

四十九、盘面错位命名

多个盘面同步旋转。

如果盘面 0 最后一个扇区读完:

盘面0:...7

下一个逻辑块可能:

盘面1:0

如果两个盘面编号完全对齐,等切换磁头完成时:

盘面1的0已经转过去

又要等一圈。

因此不同盘面可以:

错位编号。

思想仍然是:

提前补偿处理/切换需要的时间。

五十、一个很重要的存放原则

资料最后专门问:

如果一个磁道放不下数据,是继续放同一盘面的下一个磁道,还是同一柱面的另一个盘面?

应该优先:

同一柱面的不同盘面。

为什么?

同一柱面:

不用移动磁头臂

只需要切换:

磁头

而同一盘面的另一个磁道:

必须寻道

寻道很慢。

所以:

同一柱面不同盘面

通常更高效。

五十一、SSD 固态硬盘

SSD 和机械磁盘最大的区别:

机械磁盘:
盘片 + 磁头 + 机械运动

SSD:
Flash闪存

所以 SSD 没有:

机械寻道
旋转延迟

因此随机访问快很多。

SSD 主要由:

Flash芯片
+
FTL闪存翻译层

构成。

FTL:

Flash Translation Layer。

主要把:

逻辑块地址
 ↓
物理闪存页

完成地址映射。

资料指出 FTL 的作用类似传统磁盘的控制器。

五十二、SSD 的页和块

SSD 要牢记一句:

读写以页为单位,擦除以块为单位。

结构:

块 Block
 ├─ Page0
 ├─ Page1
 ├─ Page2
 ├─ ...
 └─ Page127

可以:

读一页
写一页

但不能:

擦除一页

必须:

整块擦除

所以修改一个已经写过的页可能很麻烦。

例如某块:

P0 有效
P1 有效
P2 需要修改
P3 有效

不能简单覆盖 P2。

往往需要:

复制P0
复制P1
写新的P2
复制P3
 ↓
写入新块
 ↓
擦除旧块

因此:

SSD 随机写比随机读复杂。

五十三、为什么 SSD 不需要传统磁盘调度?

机械磁盘调度的核心目标:

减少磁头移动

但 SSD:

没有磁头

所以:

FCFS
SSTF
SCAN

这种基于机械寻道距离的算法意义就弱很多。

相关模拟题也明确指出:

机械硬盘的磁盘调度算法不一定适用于 SSD。

五十四、★★★★★ SSD 磨损均衡

Flash 的问题:

一个块能擦写的次数有限。

假如:

Block0 擦写1000次
Block1 擦写10次

Block0 会很早坏。

因此控制器要:

让不同物理块擦写次数尽量均匀。

这就是:

Wear Leveling,磨损均衡。

动态磨损均衡

有数据要写的时候:

优先选择擦写次数比较少的空闲块。

例如:

A:900次
B:800次
C:100次

新数据优先写:

C

静态磨损均衡

更进一步。

有些块里放的是:

很少变化的数据

例如系统静态文件。

这些块:

几乎不写

而其他块天天写。

静态磨损均衡会主动:

搬迁长期不变的数据

让低磨损块承担更多后续写操作,从而让整个 SSD 的磨损更加平均。

五十五、这一章最容易错的几组概念

中断 vs DMA

中断:

设备 → CPU → 内存

DMA:

设备 → 内存

但:

DMA 完成后仍可中断 CPU。

Buffer vs Cache

Buffer:

缓和生产速度和消费速度不同。

Cache:

保存副本,减少重复访问慢设备。

设备控制器 vs 设备驱动程序

设备控制器:

硬件。

设备驱动程序:

软件。

中断处理程序 vs 驱动程序

驱动:

启动设备、设置设备。

中断处理程序:

设备完成后处理事件。

逻辑设备 vs 物理设备

逻辑设备:

“打印机”

物理设备:

HP-LaserJet-03

LUT:

逻辑设备 → 物理设备

独占设备 vs 虚拟设备

打印机本身:

独占设备。

用了 SPOOLing:

逻辑上变成虚拟共享设备。

物理格式化 vs 逻辑格式化

物理格式化:

组织磁道、扇区及控制信息。

逻辑格式化:

建文件系统。

SCAN vs C-SCAN

SCAN:

来回服务

C-SCAN:

只沿一个方向服务

LOOK vs SCAN

SCAN:

可移动到物理端点。

LOOK:

只移动到最远请求。

五十六、把整个第 5 章浓缩成一张逻辑图

                 第5章 I/O管理
                       │
      ┌────────────────┼────────────────┐
      │                │                │
   I/O基础          设备独立软件        外存
      │                │                │
      │                │                │
  I/O设备             Buffer           磁盘结构
      │                │                │
  设备控制器          Cache            格式化
      │                │                │
  I/O端口            设备分配           磁盘调度
      │                │                │
  独立/统一编址       DCT/COCT           FCFS
      │               CHCT/SDT           SSTF
      │                │                SCAN
  I/O控制方式         LUT                C-SCAN
      │                │                LOOK
  轮询                SPOOLing           C-LOOK
      ↓                                  │
   中断                                 SSD
      ↓                                  │
    DMA                                 FTL
      ↓                                  │
    通道                               磨损均衡

五十七、考研复习时建议重点掌握到什么程度?

本章不需要像进程同步、虚拟内存那样大量做综合大题,但必须把几个高频点做到“看到题立即反应”。根据资料中的真题追踪,建议至少熟练掌握下面这一组内容:

  1. I/O 四种控制方式:轮询、中断、DMA、通道的 CPU 干预程度、数据传输单位和数据路径。
  2. DMA 完整过程:CPU 初始化 MAR/DC → DMA 控制器搬块 → 完成中断。
  3. I/O 四层软件结构:用户层 → 设备独立层 → 驱动 → 中断处理。
  4. 单缓冲和双缓冲公式:
  1. 设备分配结构顺序:
SDT → DCT → COCT → CHCT
  1. 逻辑设备与物理设备、LUT、设备独立性。
  2. SPOOLing 的输入井/输出井、输入/输出缓冲区、输入/输出进程,以及“独占设备虚拟为共享设备”的本质。
  3. 磁盘访问时间:
  1. FCFS、SSTF、SCAN、C-SCAN、LOOK、C-LOOK 的访问顺序和磁头移动距离计算。
  2. 物理格式化、分区、逻辑格式化 的区别。
  3. SSD:读写按页、擦除按块;FTL;随机写为什么慢;动态/静态磨损均衡。

这些内容基本覆盖了资料所标注的主要历年考点以及这里模拟题中出现频率最高的知识。尤其是 I/O 控制方式、缓冲计算、SPOOLing、设备分配、磁盘调度,应该作为第 5 章第一优先级。

如果把整章最后压缩成一句话,可以记成:

第 5 章其实就是研究:怎样让慢速、种类繁多的外设在操作系统统一管理下,与高速 CPU 高效并行工作;前半章靠中断、DMA、驱动、缓冲和 SPOOLing,后半章靠磁盘调度和 SSD 管理提高外存 I/O 效率。

On this page

一、第 5 章到底在研究什么?二、5.1 I/O 管理概述1. I/O 设备分类三、I/O 接口和设备控制器I/O 端口四、I/O 端口的两种编址方式1. 独立编址2. 统一编址五、★★★★★ 高频核心:四种 I/O 控制方式六、程序直接控制方式——轮询七、中断驱动方式八、中断方式为什么还不够好?九、★★★★★ DMA 方式十、DMA 控制器四个重要寄存器十一、DMA 和中断最容易混淆的地方十二、通道控制方式十三、★★★★★ I/O 软件的层次结构用户层软件设备独立性软件设备驱动程序中断处理程序十四、用一次 write 理解整个层次十五、应用程序 I/O 接口字符设备接口块设备接口网络设备接口十六、阻塞 I/O 与非阻塞 I/O阻塞 I/O非阻塞 I/O十七、★★★★★ 缓冲技术十八、★★★★★ 单缓冲计算十九、★★★★★ 双缓冲二十、循环缓冲与缓冲池二十一、Buffer 和 Cache 不要混二十二、★★★★★ 设备分配与回收DCTCOCTCHCTSDT二十三、★★★★★ 设备分配访问顺序二十四、设备分配算法二十五、设备分配和死锁安全分配不安全分配二十六、★★★★★ 设备独立性二十七、LUT:逻辑设备表二十八、★★★★★ SPOOLing 假脱机技术二十九、SPOOLing 的组成三十、“假脱机”为什么叫假脱机?三十一、★★★★★ 从 scanf 看完整 I/O 流程三十二、5.3 磁盘结构三十三、磁盘容量计算三十四、磁盘读取一个块究竟怎么找?三十五、物理格式化、分区、逻辑格式化物理格式化分区逻辑格式化三十六、引导块三十七、坏块三十八、★★★★★ 磁盘访问时间寻道时间平均旋转延迟数据传输时间三十九、为什么磁盘调度主要优化寻道时间?四十、★★★★★ FCFS 磁盘调度四十一、★★★★★ SSTF四十二、★★★★★ SCAN 电梯算法四十三、C-SCAN四十四、LOOK 与 C-LOOK四十五、磁盘调度算法怎么做题最快?四十六、FCFS / SSTF / SCAN / C-SCAN 总对比四十七、NStepSCAN 和 FSCAN四十八、减少旋转延迟:交替编号四十九、盘面错位命名五十、一个很重要的存放原则五十一、SSD 固态硬盘五十二、SSD 的页和块五十三、为什么 SSD 不需要传统磁盘调度?五十四、★★★★★ SSD 磨损均衡动态磨损均衡静态磨损均衡五十五、这一章最容易错的几组概念中断 vs DMABuffer vs Cache设备控制器 vs 设备驱动程序中断处理程序 vs 驱动程序逻辑设备 vs 物理设备独占设备 vs 虚拟设备物理格式化 vs 逻辑格式化SCAN vs C-SCANLOOK vs SCAN五十六、把整个第 5 章浓缩成一张逻辑图五十七、考研复习时建议重点掌握到什么程度?