前面各章里的 CPU 和主存都是纳秒级的速度,而键盘、打印机这类外部设备慢上几个数量级,还各按各的节奏工作。输入输出系统要解决的就是这组矛盾:CPU 怎么跟速度、特性各异的设备交换信息。本章先看 I/O 系统的职责与设备特性,再看 I/O 接口这个中介的软硬件结构,最后按 CPU 介入程度从深到浅梳理几种 I/O 控制方式:程序查询、中断驱动和 DMA。
一、I/O 系统的职责与设备特性
I/O 系统承担两类信息交换:CPU 与外部设备之间的信息交换,以及外部设备与主存之间的信息交换。设备分输入设备和输出设备两类,键盘、鼠标属于前者,显示器、打印机属于后者。
决定 I/O 系统怎么设计的,是设备的三个特性。
异步性:CPU 运算速度极快(纳秒级),而 I/O 设备的数据处理和传输速度极慢(毫秒级甚至更慢)。如果强制用公共时钟同步,CPU 就要持续等待慢速设备完成操作,运算资源被大量浪费。所以 I/O 采用异步通信:设备自主准备数据(硬盘读取、等待按键触发)期间,CPU 执行其他进程或任务;仅当设备完成数据处理后,通过中断机制主动向 CPU 发信号,CPU 才暂时中断当前任务、执行中断服务程序为设备服务,再返回断点继续原任务。"并行 + 中断"让 CPU 和 I/O 设备解耦依赖,双方在各自节奏下工作。
实时性:不同速度的设备在准备好数据后,都需要 CPU 及时响应处理。慢速设备(键盘、鼠标的按下)不及时响应会影响用户体验;高速设备(万兆网卡、高速数据采集卡)的数据不及时处理会产生数据丢失;实时测控设备的信息不及时处理,可能导致严重事故甚至灾难。
独立性:通过软硬件分层抽象,屏蔽不同 I/O 设备的差异,降低 CPU 与设备在连接、控制上的复杂度。硬件层面,各类设备采用标准总线接口与 CPU 连接,以一致方式接入系统,减少硬件设计的多样性和复杂度;软件层面,不同设备采用统一的访问调用接口,使输入输出与具体设备类型无关,程序无需关注设备的硬件细节。

二、I/O 接口:CPU 与设备之间的中介
功能
I/O 接口的功能包括:设备寻址、设备控制、状态检测、数据交互、数据缓冲、格式转换、中断、时序控制和数据检错。
结构
- 数据缓冲器 DBR:CPU 进行读操作时,暂存从 I/O 设备读取的数据,进而被 CPU 通过总线读入寄存器;CPU 进行写操作时,暂存 CPU 送来的数据,最终输出到对应的 I/O 设备。
- 设备命令寄存器 DCR:接收 CPU 发来的设备控制命令,实现对设备的控制。
- 设备状态寄存器 DSR:保存设备是否就绪等状态,供 CPU 查询,后文的程序查询和中断驱动都要读它。
- 设备存储器 RAM(非必须):部分设备自带存储器,如 DRAM。
- 地址译码:对地址总线传来的地址信号进行译码。
- 控制逻辑:根据 CPU 通过数据总线发来的控制命令,协调接口内部各寄存器的工作流程。
接口编址
编址方式决定了 CPU 用什么指令访问接口,分两种。统一编址:设备地址与主存地址统一编址,按不同的地址区域来区分设备接口,不需要专用的 I/O 指令,用普通访存指令就能操作接口,代价是占用一部分主存地址空间。独立编址:I/O 地址与主存地址空间相互独立,必须使用专用的 I/O 指令访问 I/O 设备。
软件架构
在现代计算机系统中,用户不能直接访问 I/O 设备,必须通过操作系统间接访问并控制。操作系统向用户提供层次结构的 I/O 软件,从上到下分三层:
- 与系统无关的 I/O 库函数(用户态):如 C 语言的 printf、scanf、fopen、fread 等。这一层增加缓冲机制,尽量减少对下层系统调用库的调用,也就减少了用户态到内核态的上下文切换,提升性能;同时向上提供与操作系统无关的接口,方便程序在不同操作系统之间移植。
- 与设备无关的系统调用(内核态):用户程序通过访管指令进入内核态;系统调用库(如 UNIX 中的 open、read、write、seek、ioctl、close)向上层提供统一的 I/O 调用接口,屏蔽 I/O 设备的具体访问细节。
- 设备驱动程序(内核态):通过具体的 I/O 指令或访存指令访问 I/O 接口中的 DBR、DCR、DSR,与具体设备进行数据和命令交互;设备的中断服务程序通常也包含在驱动程序中。

三、I/O 控制方式总览
I/O 控制方式指 CPU 与 I/O 设备进行信息交互时所采用的控制方式,按 CPU 介入程度和实现手段分五类(图 3):
- 程序直接控制(查询)方式:CPU 按独占式查询或定时轮询策略读取 I/O 接口的状态寄存器 DSR,检查设备是否就绪,这期间 CPU 完全或部分被占用。
- 中断驱动方式:设备完成自身操作后主动向 CPU 发出中断请求,CPU 在等待期间可以执行其他任务,收到请求后再处理数据传送,提高了 CPU 利用率。
- 直接存储器存取(DMA)方式:在 DMA 控制器的管理下,数据直接在 I/O 设备与主存之间成批传送,传送过程完全独立于 CPU,仅在开始和结束时需要 CPU 干预。
- 通道控制方式:通道是一个专用于 I/O 操作、可执行简单通道程序的处理器,CPU 只需发出一个 I/O 指令启动通道,之后由通道独立管理整个 I/O 过程,能力比 DMA 更强。
- I/O 处理机方式:通道方式的进一步发展,功能更接近通用处理器,拥有独立的指令系统和存储,能处理更复杂的 I/O 任务和差错回复,进一步把 CPU 从 I/O 负担中解放出来。
前两种主要由软件实现,适用于数据传送速率较低的 I/O 设备;后三种主要由硬件实现,适用于数据传送速率比较高的 I/O 设备。

四、程序直接控制(查询)方式
基本思想:CPU 通过执行一段 I/O 程序实现与 I/O 设备的数据交换,这是最原始、最简单的 I/O 控制方式。有两种具体形式:
- 程序查询方式(又称轮询方式,Polling):每次数据传送前,CPU 必须主动查询 I/O 设备状态,属于有条件传送方式(设备就绪后才操作)。I/O 程序通过与接口中的命令寄存器 DCR、状态寄存器 DSR、数据缓冲寄存器 DBR 交互,实现设备控制和传输。
- 直接传送方式:无需查询 I/O 设备状态,直接进行数据交互,属于无条件传送方式。可视为程序查询方式的特例,一般适用于非常简单的 I/O 设备(如开关、LED 显示)。
查询式控制又分两种策略。忙等待(独占式查询,Busy-waiting):CPU 发出命令和参数启动设备后,原地反复轮询设备状态,直到就绪才进行数据传输,等待期间 CPU 完全被占用。定时轮询(Polling):CPU 启动设备后同时设置定时器,转去执行其他进程;定时中断到来时进入中断服务查询设备状态,若已就绪则唤醒原进程回来传输数据。
两种策略的取舍与设备速度有关:慢速设备比较适合定时轮询,快速设备的定时轮询开销大。程序直接控制方式的 I/O 接口设计简单、容易实现,常见于早期单任务操作系统中。
现代多任务操作系统在多任务引导成功之前,必须使用程序直接控制(查询)方式与 I/O 设备进行数据交互,键盘、磁盘、显示器等设备都必须支持这种方式。


五、中断驱动方式
I/O 设备完成自身操作后,主动向 CPU 发出中断请求,这就是中断驱动方式。与程序查询相比:独占式查询要 CPU 反复读 DSR 轮询,中断驱动不需要;定时轮询要为定时器选一个合适的定时中断间隔,中断驱动由设备主动请求,更具有实时性,不存在间隔选择问题。中断驱动方式有效消除了 CPU 的轮询开销,极大提高了 I/O 效率,是现代计算机中普遍采用的重要技术。
不过它仍有时间开销:进程调度的两次上下文切换时间,加上中断服务程序自身的开销。中断驱动方式提升 I/O 效率的前提,是这些额外开销小于设备准备数据的时间,因此它适合慢速设备。对极高速的 I/O 设备,准备数据的时间比上述开销还短,用中断驱动的效率反而比程序查询的独占式查询更低------独占式查询在一些高速设备中也被普遍采用,例如 NVMe SSD 处理同步 I/O。

中断的分类
内部异常由 CPU 执行指令引起,如未定义指令、越权指令、段页故障、存储保护异常、数据未对齐、除零异常、运算溢出、自陷调用、程序断点等,一般具有可预测性或可再现性(未定义指令再次执行仍将产生异常)。外部中断由 CPU 外部事件引起,大部分由外部设备触发,如定时器中断、I/O 信息传送请求中断、I/O 信息传送结束中断、I/O 接口和外部设备故障中断等,与执行的程序无关,不具备可预测性和可重复性。
内部异常分三类:
- 故障(Fault):执行指令时发生了异常,但进行处理后异常可以解决,需要重新执行那条导致异常的指令。系统会保存一个指向导致故障的指令本身的断点,以便返回重试。典型如缺页异常:程序访问的数据不在内存中,操作系统将数据从硬盘调入内存,然后重新执行刚才那条访问指令,这次就能成功执行。
- 自陷(Trap):一种"主动的异常"。程序员编写程序时有意添加用于触发异常的指令,目的是跳转到异常处理程序;处理完后继续执行下一条指令,不重新执行触发异常的那条指令。典型如系统调用:程序执行一条特殊指令(int 0x80 或 syscall)请求操作系统服务,指令执行后自动陷入内核态,处理完请求后返回用户态继续执行下一条指令。
- 终止(Abort):一种严重的、不可恢复的错误,通常是严重的硬件错误,如内存校验错误、总线错误。系统可能只能记录错误信息并尽力安全地关机。
外部中断按能否被屏蔽分两类:
| 对比项 | 可屏蔽中断(INTR) | 不可屏蔽中断(NMI) |
|---|---|---|
| 能否被屏蔽 | 可以(由 IF 位控制) | 不可(必须响应) |
| 优先级 | 最低 | 最高 |
| 与关中断的关系 | 关中断时(IE 无效)被忽略 | 关中断时依然响应 |
| 典型应用 | 普通外设(键盘、磁盘、网卡) | 硬件故障、掉电、关键定时器 |

向量中断与非向量中断
向量中断:每种中断源预先分配唯一的向量地址,存储在中断向量表或硬件寄存器中。设备触发中断后,硬件自动根据中断源识别对应的向量地址,CPU 直接加载向量地址指向的中断服务程序(ISR),无需额外查询步骤,响应速度快。x86 系统中,外部中断通过可编程中断控制器(PIC)生成向量号,CPU 据此从内存中读取 ISR 地址并执行。
非向量中断:多个设备可能共享同一中断请求线,硬件仅能识别"有中断发生",无法直接定位具体设备。CPU 响应中断后,需通过软件逐个查询设备状态寄存器,确定触发中断的设备,再根据查询结果通过条件分支指令跳转到对应设备的 ISR,流程相对繁琐,响应速度较慢。早期 ARM 处理器中,外部中断请求(IRQ)可能由多个外设共享,需在 ISR 开头通过读取外设状态寄存器判断具体中断源。

中断优先级与中断屏蔽技术
响应优先级指 CPU 对同时来自多个中断源的中断请求进行响应的先后次序。它在硬件设计时就已固定,难以更改,一般按中断事件的重要性和迫切性划分:不可屏蔽中断 > 内部异常 > 可屏蔽中断;内部异常中硬件终止(Abort)的优先级最高,其次是故障(Fault)、自陷(Trap)等软件异常;DMA 中断 > I/O 设备传送中断;I/O 设备传送中断中,高速设备优先于低速设备,输入设备优先于输出设备,实时控制设备优先于普通设备。
处理优先级指多重中断(嵌套中断)的实际优先级处理次序。不使用中断屏蔽技术时,处理优先级与响应优先级相同;利用中断屏蔽技术可以动态调整多重中断的实际优先级,让处理次序不再受响应次序的约束,现代计算机普遍采用。
屏蔽字如何改变处理次序:假设 CPU 在执行主程序时,设备 A、B、C 同时产生中断请求,响应优先级 A>B>C。若三者的中断屏蔽字分别是 111、011、001(对应 A、B、C 三列),则处理优先级 A>B>C,与响应优先级一致;若屏蔽字改成 100、110、111,处理优先级变成 C>B>A,与响应优先级相反,最先响应的 A 反而最后处理完。规律是:中断屏蔽字中包含比特 1 的数量越多,处理优先级就越高;每个屏蔽字中自身对应的位置 1,任何中断源都不会被自己屏蔽。


中断请求方式与中断控制器
中断请求送到 CPU 有四种方式:独立请求方式,每个设备一条请求线,CPU 可灵活处理中断优先级,实现简单但难以扩展;链式请求方式,系统扩展性好;分组链式请求方式,把上面两种结合;中断控制器方式,由中断控制器统一处理请求的汇集与判优。
以经典的 8259A 中断控制器为例(图 11):中断请求寄存器 IRR 锁存 IR0~IR7 上设备发来的请求;优先级判别器 PR 从中选出优先级最高的请求;在服务寄存器 ISR 记录正在服务的中断;中断屏蔽寄存器 IMR 按位屏蔽请求;控制逻辑与读/写逻辑通过数据总线缓冲器、RD/WR/CS 等信号与 CPU 交换数据。CPU 侧的中断逻辑则汇集内部异常和不可屏蔽中断 NMI,可屏蔽中断 INTR 要先经过中断使能标志位 IE/IF 的与门,关中断时被挡在门外。

单级与多重中断的处理流程
单级中断的处理流程分两段(图 12):中断响应阶段由硬件自动完成,做三件事------关中断、保存断点、中断识别;之后进入中断服务程序,由软件实现------保护现场、中断服务、恢复现场、开中断、中断返回。
多重中断(嵌套中断)在此基础上多了屏蔽字的操作(图 13):保护现场之后设置屏蔽字,再开中断进入中断服务;服务结束时先关中断,恢复现场和恢复屏蔽字,然后 CPU 通过总线向中断控制器或 I/O 接口发送中断结束命令 EOI------通知中断控制器当前中断处理完毕,并请求其清零在服务寄存器 ISR 中最高优先级的相应位------最后开中断、中断返回。


六、DMA 方式
程序查询和中断驱动中,数据传送都要经过 CPU:设备到接口、接口到 CPU 寄存器、寄存器再到主存。DMA 方式绕过 CPU,在 DMA 控制器(DMAC)的管理下,数据直接在 I/O 设备与主存之间成批交换。
一次 DMA 传输的过程:
- CPU 访问 DMAC 接口,设置 DMA 传输参数;
- CPU 发送命令启动 I/O 设备;
- 传输过程中 CPU 可以继续执行其他程序;
- I/O 设备需要进行 DMA 操作时,由 DMAC 向 CPU 申请总线控制权;
- DMAC 通过中断方式请求 CPU 对数据缓冲区和 DMAC 进行后续处理。
概括起来:预处理用 CPU,I/O 操作用 DMA,结束后 DMAC 通过 DMA 中断请求 CPU 收尾。
DMAC 与 CPU 会争用主存,解决方式有三种:DMA 独占访问、交替访问、周期挪用,区别在于 DMA 传输期间 CPU 让出主存使用权的方式和程度。
七、总结
这一章的主线是在速度悬殊、节奏各异的 CPU 与 I/O 设备之间传数据。设备天生异步、要求实时响应、种类繁多,于是用 I/O 接口做中介:DBR 缓冲数据、DCR 接收命令、DSR 汇报状态;编址方式决定 CPU 用访存指令还是专用 I/O 指令访问接口;驱动程序藏在操作系统分层里,把设备细节屏蔽在内核态。控制方式按 CPU 介入程度递减:程序查询全程或部分占用 CPU,中断驱动把主动权交给设备、CPU 只在有请求时介入,DMA 连数据传送都交给 DMAC,只在预处理和收尾时需要 CPU。
给一台设备选控制方式,可以固定问两个问题:设备准备一次数据要多久,CPU 处理一次传送的额外开销有多大。开销小于准备时间,用中断驱动;设备极快、开销反而占大头时,独占式查询甚至更划算;批量高速传送,交给 DMA。
参考资料
- 湖科大教书匠《计算机组成原理微课堂》