前言
计算机程序想把结果显示到屏幕、从键盘读取字符,或把文件写入磁盘,都离不开 I/O 管理。它解决的核心问题是:CPU、内存与外部设备的速度和工作方式并不相同,操作系统需要在它们之间完成控制、数据传送、资源分配与性能协调。

本章可以沿着一条清晰的链路理解:CPU 先通过控制器向设备下达命令,再选择合适的控制方式传输数据;操作系统用分层软件屏蔽硬件差异,用假脱机、设备分配和缓冲机制协调多个进程;最后落到磁盘和 SSD 的实际存储与访问上。
一、I/O 设备与 I/O 控制器
I/O 是输入与输出的简称。键盘、鼠标属于输入设备,显示器、打印机属于输出设备,磁盘既能读入也能写出数据。
按信息交换单位划分,设备可分为两类:
- 块设备:以块为单位传送数据,通常支持随机访问,因此能够定位并读写指定块,例如磁盘。
- 字符设备:以字符流为单位传送数据,通常不能按块随机寻址,例如键盘、鼠标等。
CPU 不会直接处理设备的机械动作。设备一般由机械部件和电子部件构成:机械部件负责具体操作,电子部件中的 I/O 控制器负责接收 CPU 命令、汇报设备状态、暂存输入输出数据,并完成地址识别。

控制器与 CPU 之间通常包含控制、状态和数据相关寄存器。CPU 通过控制寄存器下达命令,通过状态寄存器了解设备是否就绪或是否出错,通过数据寄存器暂存待传送的数据。
控制器寄存器有两种编址思路:内存映射 I/O 将寄存器统一编入内存地址空间,可以使用访问内存的指令操作;寄存器独立编址则让控制器寄存器拥有单独地址空间,需要专门的 I/O 指令。
二、I/O 控制方式:CPU 参与程度逐步降低
I/O 控制方式讨论的是 CPU 如何组织设备读写。理解四种方式时,可以始终对比三个问题:CPU 是否要反复等待、每次传输多大单位、数据是否必须经过 CPU。
1. 程序直接控制方式
CPU 发出 I/O 命令后持续轮询设备状态,设备未就绪时就反复检查;就绪后,每次只传送一个字。读操作的数据路径是"设备 → CPU → 内存",写操作则相反。
这种方式实现简单,但 CPU 会把大量时间花在等待设备上,利用率较低。
2. 中断驱动方式
CPU 发出命令后不再原地等待,可以调度其他进程运行。设备完成 I/O 后,控制器向 CPU 发出中断;CPU 保存当前执行现场,转去执行中断处理程序,并在其中处理完成事件、唤醒原先阻塞的 I/O 进程,使其回到就绪队列。
数据仍要经由 CPU 传递,但 CPU 与设备已经能够并行工作。代价是每传送一个字都可能触发一次中断,频繁中断会带来 CPU 开销。
3. DMA 方式
DMA 的传输单位是块。CPU 只需设置设备、内存地址和传送长度等参数,DMA 控制器就可以在设备与内存之间完成成块数据传送,数据不再经过 CPU。传输完成后,DMA 控制器再以一次中断通知 CPU。
DMA 内部仍可能按字暂存和搬运数据,但对 CPU 来说,干预频率已经从"每个字"降为"每一块"。
4. 通道控制方式
通道可看作专门负责 I/O 的处理部件。CPU 发出命令后,通道执行通道程序完成 I/O,并在结束时通知 CPU。一个通道可以控制多个 I/O 控制器,一个控制器又可连接多个设备。

从程序直接控制到通道控制,演进方向始终一致:减少 CPU 对琐碎 I/O 过程的干预,让 CPU 有更多时间执行计算或调度其他任务。
三、I/O 软件层次:统一接口与硬件细节分离
应用程序并不需要了解网卡寄存器或磁盘控制器的具体结构。操作系统通过分层,把"使用设备"和"控制硬件"隔离开来。
从上到下可以分为以下层次:
- 用户层软件:向上层应用提供 API,由应用发起 I/O 请求。
- 设备独立性软件:提供统一调用接口,负责设备保护、差错处理、设备分配与回收、缓冲区管理,以及逻辑设备名到物理设备名的映射。
- 设备驱动程序:面向具体硬件,执行设置控制器寄存器、检查状态等控制操作。
- 中断处理程序:设备完成 I/O 后处理控制器发来的中断,并完成后续的数据处理和进程唤醒。
设备独立性软件的价值在于屏蔽差异。用户程序可用统一的逻辑设备名请求服务,系统再根据设备类型找到实际的物理设备和驱动程序。不同厂商设备的内部特性不同,因此需要各自对应的驱动程序;统一的驱动接口则让操作系统内核不必因更换具体设备而改变上层调用方式。
常见接口也体现了这种抽象:字符设备常见 get/put 操作,块设备提供 read/write 与调整读写位置的 seek;网络通信中,socket 创建套接字,bind 绑定端口,connect 建立点对点连接,随后再通过 read/write 进行数据读写。
阻塞 I/O 中,进程会等待操作完成,例如等待键盘输入;非阻塞 I/O 则可以先完成数据复制并继续执行,底层设备操作由内核在后续阶段处理。
四、假脱机技术:让打印机看起来能被多人同时使用
脱机技术原本依靠外围控制机和高速设备,把输入输出从主机 CPU 的直接控制中分离出来。假脱机技术(SPOOLing)用软件模拟这一过程,将数据先放入磁盘和内存缓冲区,再由输入进程、输出进程与用户进程并发完成后续工作。

以共享打印机为例,用户进程不需要一直占用打印机。它先将待打印数据写入磁盘缓冲区,再提交打印请求;系统把请求放入假脱机文件队列,输出进程按照队列依次取出任务并驱动打印机工作。
打印机本来是独占设备,同一时间只能服务一个任务。经过 SPOOLing 后,多个进程可以在宏观上同时提交打印任务,打印机被虚拟为共享设备。该机制依赖多道程序技术,因为输入进程、输出进程和用户进程需要并发推进。
五、设备的分配与回收
设备分配需要同时考虑设备属性、分配算法和安全性。
- 独占设备:一段时间只能分给一个进程,例如打印机。
- 共享设备:可供多个进程宏观上同时使用、微观上交替使用,例如磁盘。
- 虚拟设备:通过 SPOOLing 将独占设备改造成可共享使用的设备。
从安全性看,安全分配方式在进程获得一个设备后将其阻塞,直到本次 I/O 完成再唤醒。它破坏了死锁的"请求和保持"条件,但 CPU 与 I/O 对该进程会串行工作。不安全分配方式允许进程在获得设备后继续执行并请求其他设备,计算和 I/O 可以并行,但可能产生死锁。
静态分配在进程运行前分配全部所需资源,运行结束后统一归还,也能破坏请求和保持条件;动态分配则在运行过程中按需申请资源。

设备管理常用的数据结构包括:
- 系统设备表 SDT:记录系统中所有设备的总体信息。
- 设备控制表 DCT:记录一个设备的类型、标识、状态、等待队列和指向控制器的指针等。
- 控制器控制表 COCT:记录控制器状态、等待队列及与通道的关联。
- 通道控制表 CHCT:记录通道状态和等待队列。
传统分配链路为:根据物理设备名查询 SDT,找到 DCT 分配设备;再根据 DCT 找到 COCT 分配控制器;最后根据 COCT 找到 CHCT 分配通道。设备、控制器和通道都成功分配后,I/O 才能启动。
直接使用物理设备名会暴露硬件细节:设备更换时程序需要修改;目标设备忙碌时,即使存在同类设备也只能等待。改进方式是建立逻辑设备名与物理设备名的映射表,让用户只面对稳定的逻辑名称。
六、缓冲区管理:协调速度与数据粒度
缓冲区是在内存中开辟的一段临时存储区域。它有四个直接作用:缓和 CPU 与设备的速度差异,减少中断频率,解决数据粒度不匹配,提高 CPU 与 I/O 设备之间的并行性。

1. 单缓冲
主存只设置一个大小为一块的缓冲区。设备将数据填满缓冲区后,进程才能取走;缓冲区未腾空前,设备不能继续写入。
若设备输入一块数据耗时为 T,进程将数据从缓冲区移到工作区耗时为 M,处理该块耗时为 C,则单缓冲处理一块数据的平均耗时为:
text
max(C, T) + M
2. 双缓冲
双缓冲使用两个缓冲区:一个供设备填充时,另一个可供进程取数并处理,因此二者能更充分重叠。处理一块数据的平均耗时为:
text
max(T, C + M)
双缓冲也可支持两个主机间的双向数据传送。
3. 循环缓冲区与缓冲池
循环缓冲区将多个缓冲区组织成循环队列,in 指针指向下一块空缓冲区,out 指针指向下一块满缓冲区,适合连续生产和消费数据。
缓冲池把缓冲区统一管理,通常维护空缓冲队列、输入队列和输出队列。输入进程从空队列取缓冲区填充,填满后挂到输入队列;计算进程从输入队列取满缓冲区,读空后归还空队列。输出方向则以类似方式在空队列和输出队列之间流转。这样可以让多个输入、计算、输出任务共享一组缓冲资源。
七、磁盘结构、初始化与调度
机械磁盘由表面涂有磁性物质的盘片组成。盘片被划分为磁道,磁道又分为扇区;多个盘片叠放形成多个盘面,同一相对位置的磁道组成柱面。磁盘物理地址通常写作"柱面号、盘面号、扇区号"。

一次读写的时间可拆分为三部分:
- 寻找时间:启动磁臂并将磁头移动到目标磁道所需的时间。
- 延迟时间:目标扇区旋转到磁头下方所需的时间。
- 传输时间:实际读写数据所需的时间。
磁盘初始化通常经历物理格式化、分区和逻辑格式化。物理格式化会划分扇区;分区形成 C、D、E 等逻辑区域;逻辑格式化建立文件系统及其空间管理数据结构。引导程序需要在启动时完成系统加载,ROM 中保存很小的自举装入程序,完整的引导程序位于引导块。对于坏块,简单磁盘可在逻辑格式化时标记,较复杂的磁盘可由控制器维护坏块链并管理备用扇区。

磁盘调度算法
磁盘调度的目标是减少磁头移动和等待时间。
- 先来先服务 FCFS:按请求到达顺序处理,公平直观,但寻道路径可能较长。
- 最短寻找时间优先 SSTF:优先响应距离当前磁头最近的请求,能降低当前寻道开销,但远处请求可能长期得不到服务而饥饿。
- 扫描算法 SCAN:磁头沿一个方向移动并服务沿途请求,到最外侧磁道后再反向,类似电梯运行。
- 循环扫描 C-SCAN:只在一个方向上服务请求,到边界后直接回到起始端再继续,响应更均匀。
- LOOK 与 C-LOOK:分别是 SCAN 与 C-SCAN 的改进。当当前移动方向上已没有请求时,磁头立即转向或返回,不必移动到物理边界。

减少延迟时间还可以利用交替编号和错位命名。其共同思路是让逻辑上连续访问的扇区在物理位置上留出适当间隔,使系统处理完前一扇区后能够及时读入下一扇区。

八、固态硬盘 SSD
SSD 使用闪存作为存储介质,通过电路定位数据,因此没有机械硬盘的寻道时间和旋转延迟,随机访问性能较高,也更安静、抗震、低功耗,但成本通常更高。

SSD 的闪存芯片由块和页组成:以页为单位读写,以块为单位擦除。一个已写入数据的页不能直接覆盖写入,常见做法是将有效数据迁移到已擦除的新块,再写入新数据。因此 SSD 往往表现为读快、写慢。
闪存块的擦除次数有限,长期反复写同一块会缩短其寿命。磨损均衡技术把擦除和写入任务分散到不同闪存块:动态磨损均衡优先选择累计擦除次数较少的块写入;静态磨损均衡还会迁移数据,让长期保存数据的旧块更多承担读取任务,让较新的块承担更多写入任务。
总结
I/O 管理的重点不只是记住四种控制方式或几种磁盘调度算法,更要理解操作系统如何逐层降低 CPU 的等待与干预:控制器连接硬件,DMA 和通道承担传送,设备独立性软件统一接口,假脱机和缓冲机制协调多个进程,磁盘调度与 SSD 管理进一步改善存储访问效率。
掌握这条"控制---传送---管理---优化"的主线,遇到 I/O 相关概念时就能快速定位它解决的是哪一段问题。
参考资料
- 操作系统王道考研第五章:输入输出(I/O)管理