IO管理:从轮询到通道
本篇对应王道第五章(原 17 IO管理概述 + 18 设备独立性软件合并)。主线一句话:想尽办法减少 CPU 对 IO 的干预——四种控制方式是这条主线的四步进化,缓冲区、SPOOLing 是配套工具。
一、I/O 设备与控制器
IO 管理是 OS 设计中最凌乱也最具挑战的部分——设备五花八门,很难有通用一致的设计。
设备分类(按不同维度)
| 维度 | 分类 |
|---|---|
| 信息交换单位 | 块设备(以块为单位,传输速率高、可寻址可随机读写,如磁盘)/ 字符设备(以字符为单位,速率低、不可寻址,常用中断 IO,如键盘、打印机) |
| 传输速率 | 低速(键盘鼠标,几~几百 B/s)/ 中速(激光打印机)/ 高速(磁盘、光盘) |
| 使用特性 | 存储设备 / 输入输出设备(输入、输出、交互式) |
| 共享属性 | 独占设备(同一时刻只能一个进程用,如打印机)/ 共享设备(时间段内多进程分时访问,如磁盘)/ 虚拟设备(SPOOLing 把独占改造成共享) |
设备控制器:CPU 与设备之间的中间人
**I/O 接口(设备控制器)**接收 CPU 命令、控制设备工作,把 CPU 从繁杂的设备控制事务中解脱出来。三部分组成:
- 与 CPU 的接口:数据线(数据/控制/状态信息)、地址线(寄存器编号)、控制线(读写信号)
- 与设备的接口:一个控制器可连多个设备,每接口传数据、控制、状态三类信号
- I/O 逻辑:对 CPU 命令译码,控制所选设备
六大功能:接收识别命令、数据交换、报告设备状态、地址识别、数据缓冲、差错控制。
I/O 端口与编址
I/O 端口 = 控制器中可被 CPU 直接访问的寄存器:数据寄存器(缓存输入输出数据)、状态寄存器(设备状态供 CPU 读)、控制寄存器(CPU 写入启动命令)。
编址两种方式:
| 独立编址 | 统一编址(内存映射 I/O) | |
|---|---|---|
| 思想 | IO 端口单独一个地址空间,用专用 I/O 指令访问 | 从主存地址空间分一段给端口,普通访存指令就能访问 |
| 优点 | 地址线少、译码简单、寻址快;专用指令程序清晰 | 无需专门指令、灵活;编址空间大;保护可由虚拟存储机制实现 |
| 缺点 | 指令少灵活性差;要两组读写控制信号 | 占用主存地址空间;地址线全部参译码,电路复杂、速度慢 |
二、四种 I/O 控制方式(核心)
贯穿始终的宗旨:尽量减少 CPU 对 I/O 控制的干预,把 CPU 从繁杂 IO 事务中解放出来。
1. 程序直接控制(轮询)
CPU 发出 IO 指令后不断循环测试设备状态,直到数据就绪才取走。
简单易实现,但 CPU 绝大部分时间耗在循环测试上,CPU 与设备串行工作——根源是没有中断机构,设备无法主动报告"我好了"。
2. 中断驱动
设备准备好数据后主动中断 CPU:CPU 发出读命令后继续干别的;指令周期末尾检查中断信号,来了就保存现场、转中断处理程序、取走一个字,再恢复现场。
设备准备数据期间 CPU 和设备并行,利用率明显提升。但仍有两个问题:数据交换必须经过 CPU 寄存器;CPU 以字(节)为单位干预——对块设备 IO 极其低效。
3. DMA:数据不经过 CPU
在设备和内存之间开辟直接数据通路。三个特点:
- 传送单位是数据块(不再是字)
- 数据直接在设备和内存间传送,不经过 CPU
- 仅在一个/多个数据块的开始和结束才需要 CPU 干预
DMA 控制器四类寄存器:CR(命令/状态)、MAR(内存地址)、DR(数据)、DC(数据计数器)。工作流程:CPU 设置初值启动 DMA → DMA 控制器全权负责传送(每次一个字,不需 CPU)→ 整块传完发一个中断。
4. 通道:让"小型处理机"管 IO
通道是一种特殊的处理机,能执行一系列通道指令。CPU 只需发一条 IO 指令(指明通道程序在内存的位置和要访问的设备),通道自己执行通道程序完成任务后再中断 CPU。实现 CPU、通道、设备三者并行。
与一般处理机的区别:指令类型单一、没有自己的内存(通道程序放主机内存,与 CPU 共享)。与 DMA 的区别:DMA 需 CPU 控制传输块大小和内存位置,通道这些信息自己控制;一个 DMA 控制器对应一台设备,一个通道可以控制多台设备。
裁缝店比喻(一图流记住四种方式)
想象客户要做一批衣服(CPU 要数据,裁缝是设备):
| 方式 | 对应场景 |
|---|---|
| 程序轮询 | 裁缝没有客户联系方式,客户每隔一会儿跑去裁缝店看做好没有——浪费时间 |
| 中断驱动 | 裁缝有联系方式,每做完一件打一个电话让客户来拿——省了瞎逛,但一件一趟还是累 |
| DMA | 客户雇一位专属秘书,交代好衣服放哪(内存地址);裁缝直接联系秘书,秘书取回放好,每 100 件报告一次——大幅省时 |
| 通道 | 秘书权力更大:自己决定衣服存哪、何时报告(100 件还是 10000 件);且能同时对接多位裁缝——CPU、通道、多设备全并行 |
三、I/O 软件层次结构
从上到下四层,每层利用下层服务、屏蔽实现细节、向上提供服务;接口不变,改一层不影响别层;只有最低层涉及硬件:
| 层次 | 职责 |
|---|---|
| 用户层软件 | 库函数(如 printf),通过系统调用获取 OS 服务 |
| 设备独立性软件 | 统一接口、设备命名/保护、分配与回收、逻辑设备名→物理设备名映射、缓冲管理、差错控制、统一逻辑块 |
| 设备驱动程序 | 与硬件直接相关:把抽象请求(read/write)转成设备命令发给控制器;每类设备一个驱动 |
| 中断处理程序 | 保存被中断进程环境、处理后恢复现场;与硬件紧密相关,放最底层并尽量屏蔽 |
一次 read 的完整旅程:用户调 read(用户层)→ 设备独立层解析统一命令 → 驱动层把 read 翻译成该设备特有的指令(磁盘和打印机行为不同)→ 中断处理程序接管执行 → 硬件控制器按命令操控设备完成。
应用程序 I/O 接口
- 字符设备接口:get/put(顺序存取,缓冲区收发字符)、in-control 通用指令(参数对应各设备特定功能)、open/close 实现互斥共享
- 块设备接口:磁盘二维结构(磁道号+扇区号)被隐藏成线性编号 0~n-1;抽象命令映射为低层操作;常配 DMA;内存映射接口把文件映射到内存读写
- 网络设备接口:套接字接口(socket),本地套接字连接远程套接字收发数据
阻塞 I/O 与非阻塞 I/O
- 阻塞 I/O:进程发起 IO 后被移入阻塞队列干等,IO 完成才唤醒。奶茶店点单守着等——不知道啥时候做好,只能一直等。简单,适合并发小
- 非阻塞 I/O:发起 IO 后不阻塞,但需不断轮询询问是否完成,等待期间能干别的。点完单顺便逛商场,隔一会儿来问一次。并发量大时合适,缺点是轮询占 CPU
四、高速缓存与缓冲区
缓冲区要解决什么
- 缓和 CPU 与 IO 设备速度不匹配的矛盾
- 减少中断频率,放宽中断响应时间限制
- 解决数据粒度不匹配(设备按字、进程按块)
- 提高 CPU 与设备的并行性
实现:硬件缓冲器太贵(只在关键部位用),一般用内存。共享资源 → 使用时必须互斥。
单缓冲
一块缓冲区。设设备输入一块耗时 T、缓冲区传到工作区耗时 M、CPU 处理耗时 C,缓冲区必须冲满才能取:
- T 与 C 可并行(设备往缓冲区灌数据时,CPU 处理上一块已传出的数据)
- 平均处理一块时间 = Max(C, T) + M
双缓冲
两块轮流用:设备灌缓冲区 1 的同时,CPU 取缓冲区 2 的数据。T、M、C 三者并行程度更高:
- 平均处理一块时间 = Max(C + M, T)
⚠️ 通信细节:两台机器间单缓冲只能单向传输;要双向就得各自配两个缓冲区(一个发送一个接收)。
循环缓冲
速度相差太远时双缓冲也不够用——多个缓冲区链成循环队列,in 指针指向第一个可输入的空缓冲区,out 指向第一个可提取的满缓冲区,沿链循环移动。
缓冲池
区别于缓冲区(只是一块内存):缓冲池是管理机制——数据结构 + 操作函数 + 公用缓冲区,供多进程共享。三类队列:空缓冲队列、输入队列(装满输入数据)、输出队列(装满输出数据);四种工作缓冲区(hin 收容输入 / sin 提取输入 / hout 收容输出 / sout 提取输出)。
四种工作方式:收容输入(空队首摘缓冲 → 装输入数据 → 挂输入队列尾)、提取输入(输入队列首取 → 提取数据 → 用完挂空队尾)、收容输出、提取输出——对称的四步循环。
💡 循环缓冲和缓冲池只需定性理解机理;单缓冲双缓冲按 Max 公式模板分析,以不变应万变。
高速缓存 vs 缓冲区(必考对比)
| 高速缓存 Cache | 缓冲区 Buffer | |
|---|---|---|
| 存什么 | 数据的副本 | 传输中的数据 |
| 目的 | 访问副本比访问原始数据快 | 缓和速度差异、减少 IO 次数 |
| 典型 | 磁盘高速缓存(逻辑上属于磁盘、物理上驻留内存的盘块信息)、TLB | IO 缓冲 |
磁盘高速缓存两种形式:内存中开辟固定大小缓存区;或把未利用的内存空间当缓冲池供请求分页和磁盘 IO 共享。
五、设备分配与回收
总原则:充分发挥设备使用效率(让设备忙起来)+ 避免分配不当造成死锁。
四张表(体现从属关系)
系统中通道 → 控制器 → 设备层层挂接,数据结构要体现这种层级:
| 表 | 数量 | 内容 |
|---|---|---|
| DCT 设备控制表 | 每设备一张 | 设备类型、标识符(物理名唯一)、状态(忙/闲)、指向 COCT 的指针、重复执行次数或时间、设备队列队首指针(等待该设备的 PCB 队列) |
| COCT 控制器控制表 | 每控制器一张 | 指向 CHCT 的指针 |
| CHCT 通道控制表 | 每通道一张 | 与通道连接的控制器表首址(一个通道管多个控制器) |
| SDT 系统设备表 | 全系统一张 | 所有物理设备的表目(含 DCT 入口) |
回收:进程释放设备且无其他进程请求 → 把 DCT 的设备状态改为空闲即可。
分配三步
以独占设备为例:① 按物理设备名查 SDT 找到 DCT → 看状态:忙则挂设备等待队列,闲则分配设备;② 按 DCT 找 COCT → 忙则挂控制器等待队列,闲则分配控制器;③ 按 COCT 找 CHCT → 忙则挂通道等待队列,闲则分配通道。设备、控制器、通道三者都分到,分配才算成功,才能启动传送。
分配要考虑的因素
- 固有属性:独占设备(独占分配)、共享设备(同时分给多进程、调度访问次序)、虚拟设备(可共享)
- 分配算法:FCFS(按请求顺序排队)或最高优先级优先(同优先级再按 FCFS)
- 安全性:安全分配——发 IO 请求就阻塞直到完成,不会再申请别的资源,安全但 CPU 与设备串行;不安全分配——发完请求继续跑,可能同时操作多个设备、推进快,但可能死锁
- 设备独立性:进程用逻辑设备名请求,不指定具体物理设备——好处:分配灵活(该类设备忙可换同类另一台)、易于 I/O 重定向(换设备不用改程序)
逻辑设备名 → 物理设备名靠逻辑设备表 LUT(逻辑设备名、物理设备名、驱动程序入口地址)映射。LUT 两种设置:全系统一张(单用户系统,逻辑名不能重)或每用户一张(多用户系统,不同用户可用相同逻辑名)。
六、SPOOLing:把独占设备变成"共享"
假脱机技术:用程序模拟脱机输入输出的外围控制机,将独占设备改造成共享设备。
组成:
- 输入井/输出井:磁盘上开辟的两个存储区域,模拟脱机的磁盘;输入井收容 IO 设备输入的数据,输出井收容用户程序的输出数据;每进程的输入/输出数据是一个文件,链成队列
- 输入/输出缓冲区:内存中暂存(设备 → 输入井、输出井 → 设备)
- 输入/输出进程:模拟外围控制机,搬运数据
- 井管理程序:控制作业与磁盘井之间的信息交换
打印机例子:多个进程发打印请求,SPOOLing 系统都答应,但不立即真把打印机分给谁,而是:① 在磁盘缓冲区申请空闲盘块暂存打印数据;② 申请一张空白打印请求表挂到打印队列。进程立刻拿到"已打印"的感觉就去干别的了——真打印在打印机空闲且任务排到队首时才进行,用户不可见。每个进程都觉得自己独占了一台打印机。
特点:
- 提高 IO 速度——对低速设备的操作变成对磁盘缓冲区的存取
- 独占设备改造为共享设备——实际并未给任何进程分配设备
- 实现了虚拟设备功能
为什么说是空间换时间:空间开销显然(磁盘开井);省的时间在于——没有 SPOOLing 时 CPU 向打印机输出数据就得迁就打印机的慢速度,等打完才能干别的;有了 SPOOLing,CPU 把数据甩到磁盘输出井(快)就走人,打印排队的事假脱机进程管。向磁盘写数据比向打印机写快得多,时间就省出来了。
七、设备驱动程序接口
驱动程序 = IO 系统上层与设备控制器之间的通信程序:接收抽象 IO 请求(read/write)转成具体命令发给控制器,再把控制器的信号传回上层。功能:
- 把抽象要求转为具体要求(如盘块号 → 盘面号、磁道号、扇区号)
- 检查请求合法性、了解设备状态、传递参数、设置工作方式
- 发出 IO 命令:设备空闲立即启动;忙则把请求者 PCB 挂到设备队列
- 及时响应控制器发来的中断,按类型调用相应中断处理程序
与普通程序的不同:抽象与具体的双向转换、与 IO 控制方式(中断/DMA)紧密相关、不同类型设备配不同驱动、基本部分常固化在 ROM 中、允许同时多次调用执行。
统一接口要求:每个驱动与 OS 之间有相同或相近的接口(好添加新驱动);抽象设备名转物理设备名找驱动入口;对设备保护,防止无权用户使用。
八、盲点总复习
- 四种 IO 方式的进化目标只有一句话:减少 CPU 干预——轮询全程盯 → 中断按字报 → DMA 按块报不经过 CPU → 通道自己跑程序管多设备
- 通道指令类型单一、没有自己的内存(与 CPU 共享主机内存);一个通道可控制多台设备
- 独立编址用专用 I/O 指令(要两组读写控制信号);统一编址占主存空间、译码复杂
- 单缓冲 Max(C,T)+M,双缓冲 Max(C+M,T);两机通信要双向必须各配两个缓冲区
- 磁盘高速缓存逻辑上属于磁盘、物理上在内存——不是 CPU 与内存之间那个 Cache
- 缓冲区是共享资源,使用必须互斥;缓冲池 = 缓冲区 + 管理机制,可多进程共享
- 设备分配顺序:设备 → 控制器 → 通道,三者都到手才算成功
- 安全分配方式(请求即阻塞)CPU 与设备串行;不安全分配方式推进快但可能死锁
- 设备独立性 = 用逻辑设备名,好处是灵活 + IO 重定向;映射靠 LUT,多用户系统每用户一张 LUT(逻辑名可重)
- SPOOLing 三大关键词:磁盘上的井、内存中的缓冲区、模拟外围控制机的输入输出进程;本质是以空间换时间实现虚拟设备
- 驱动程序固化在 ROM;一个驱动对应一类设备
- 字符设备不可寻址 → 顺序存取 + 中断方式;块设备可寻址 → 随机存取 + DMA
四大管理还剩最后一块拼图:磁盘调度 → 09-磁盘与固态硬盘
⬅️ 🏠 00-操作系统总览 ➡️ 09-磁盘与固态硬盘
💬 评论