引言

你敲击键盘,字符出现;点击保存,数据写入磁盘。
CPU 并不是直接跟键盘或磁盘"说话"的——中间隔着 I/O 控制器和 UNIX 提供的统一文件接口。本文拆解 I/O 设备分类体系与控制器的硬件架构,并为有工程背景的读者揭示底层设计在真实系统中的痕迹。

📌 核心要点

  • I/O 设备按使用特性(人机交互/存储/网络)、传输速率(低/中/高)和信息>交换单位(块/字符)三个维度分类 [共识]
  • 块设备可寻址、以块为单位传输;字符设备不可寻址、以字符为单位、常采>用中断驱动——408 选择题核心辨析点 [引用:王道 5.1_1]
  • I/O 控制器通过数据寄存器、控制寄存器、状态寄存器,经 CPU 接口、I/O 逻辑、设备接口三大模块充当"翻译官" [引用:王道 5.1_2]
  • 内存映像 I/O 将寄存器编址纳入内存地址空间、复用访存指令;寄存器独立编址需专用 I/O 指令

什么是 I/O 设备?——UNIX 的"一切皆文件"哲学

I/O 设备(Input/Output Device)将数据输入计算机或接收计算机的输出,属于裸机(Bare Machine)的组成部分。UNIX 将其抽象为特殊文件(Special File)——操作键盘等同于读文件(Read),向显示器输出等同于写文件(Write),用户态程序无需关心设备的具体型号或协议 [经验]。

需要记牢一对定义:Write(写) = 向外部设备写出数据(CPU → 设备),Read(读) = 从外部设备读入数据(设备 → CPU)。方向判断的视角始终是 CPU [引用:王道 5.1_1]。鼠标、键盘属于输入型,显示器属于输出型,移动硬盘可输入可输出。

常见混淆:I/O 设备是物理硬件(键盘机械轴体、磁盘磁头),设备驱动程序(Device Driver)是内核中的软件。前者在硬件层,后者在软件层——分清这一点,学习 I/O 软件层次结构时才不会概念错位 [共识]。

I/O 设备的三种分类维度——怎么给设备"贴标签"?

同一块键盘,从不同角度可贴上不同标签。三个分类维度反映的是操作系统设计者管理设备的真实决策逻辑。

按使用特性:人机交互类(鼠标、键盘、打印机)速率较低;存储设备(移动硬盘、光盘)以块传输,追求高吞吐;网络通信设备(网卡、调制解调器)关注延迟与可靠性 [共识]。这种分类影响调度策略——不会用磁盘的电梯算法去管键盘。

按传输速率:低速(几个 ~ 几百 B/s,如键盘);中速(数千 ~ 上万 B/s,如打印机);高速(数千 B/s ~ 千兆 B/s,如磁盘、网卡)。速率量级决定 I/O 控制方式:低速用程序直接控制,高速需要 DMA(直接存储器访问,Direct Memory Access)。

按信息交换单位——408 考研最重要的分类维度 [共识]。块设备(Block Device)以块为单位,可寻址,CPU 可随机访问任意块,磁盘即典型。字符设备(Character Device)以字符为单位,不可寻址,常采用中断驱动,如键盘、串口。

块设备 vs 字符设备——408 考研必考辨析

对比维度 块设备 字符设备
寻址能力 可寻址,随机读写任一块 不可寻址,顺序访问
传输单位 以"块"为单位(512B、4KB) 以字符/字节为单位
传输速率 较高 较低
典型控制方式 常采用 DMA 常采用中断驱动

注意:两个分类维度不互斥。磁盘从信息交换单位看是块设备,从使用特性看是存储设备。不要误以为块设备的本质是"按块传输"——本质是可寻址。

I/O 控制器的硬件构成——CPU 的"翻译官"

CPU 读得懂寄存器里的 0 和 1,但读不懂键盘的物理行程和磁头偏转角度。因此 CPU 无法直接控制 I/O 设备的机械部件,需要 I/O 控制器(I/O Controller,又称 Device Controller)作为中介。

I/O 设备由机械部件(磁头臂、按键弹簧等物理机构)和电子部件(I/O 控制器——主板扩充槽上的印刷电路板)组成。控制器内部三个逻辑模块:

  1. CPU 与控制器接口(Host Interface):通过数据线、地址线、控制线与 CPU 相连。
  2. I/O 逻辑(I/O Logic):负责地址译码(判断访问哪个寄存器)和命令识别(将 I/O 指令转为设备控制信号)。
  3. 控制器与设备接口(Device Interface):一个控制器可通过多接口连多个设备。例如一块 SATA 控制器挂载多块硬盘——408 考点:“一个 I/O 控制器可能对应多个设备” 。

I/O 控制器的寄存器

寄存器是控制器中 CPU 直接访问的存储单元:

  • 数据寄存器(Data Register):暂存 CPU 与设备间的数据。输入时设备放入、CPU 读取;输出时 CPU 写入、设备取走 。
  • 控制寄存器(Control Register):存放 CPU 的命令和参数。如"读磁盘第 100 扇区"——命令码和扇区号写入此寄存器。
  • 状态寄存器(Status Register):记录设备状态。典型约定 1=空闲(Idle),0=忙碌(Busy)。CPU 发命令前须先读它。
  • 地址译码:非严格意义的寄存器,是 I/O 逻辑功能——将地址信号译码以定位目标寄存器。各控制/状态寄存器可有多个实例对应不同设备 。

分设四种的原因:数据双向暂存,命令 CPU 单向下发,状态设备单向上报——方向时序不同,合并会导致读写冲突 。

内存映像 I/O vs 寄存器独立编址——两种寄存器寻址方案

CPU 如何定位控制器中的寄存器?两种方案。

内存映像 I/O(Memory-Mapped I/O):将寄存器地址映射到内存地址空间。CPU 用普通访存指令(如 MOV)即可操作控制器。优点是简化了指令,可以采用对内存进行操作的指令来对控制器进行操作。代价是寄存器挤占内存地址空间。

寄存器独立编址(Port-Mapped I/O):寄存器使用独立地址空间。CPU 需专用 I/O 指令(如 x86 IN/OUT),指令要指明寄存器地址和控制器编号 。优点是不占内存地址空间,代价是指令集复杂度增加。

两种方案的工程权衡

对比维度 内存映像 I/O 寄存器独立编址
指令复杂度 低,复用访存指令 高,需专用 I/O 指令
地址空间利用率 寄存器挤占内存地址 独立空间,互不干扰
硬件成本 需地址区分逻辑 需额外 I/O 指令译码电路
典型架构 ARM、MIPS x86(IN/OUT 指令)

工程中两种方案并存 [经验]。Linux 通过 /proc/iomem 暴露内存映像 I/O 的地址映射,/proc/ioports 暴露独立编址的端口范围——可直观看到两类编址的共存。

考点串联——从硬件到软件的全景视角

I/O 设备分类和控制器属于硬件层。往上是本系列第二篇的四种 I/O 控制方式(程序直接控制、中断驱动、DMA、通道控制),再往上是第三篇 I/O 软件层次结构(中断处理程序→设备驱动→设备独立性软件→用户层 I/O)。之前讲的系统调用与中断机制是前置知识——用户态通过系统调用进内核,内核通过中断获知 I/O 完成。

本章后续还覆盖 SPOOLing 技术(第四篇,独占设备虚拟化为共享)和设备分配与缓冲区管理(第五篇,设备争用与速率匹配)。


FAQ

Q1: 块设备和字符设备的根本区别是什么?最容易混淆的点在哪?

根本区别是寻址能力。块设备每个数据块有独立地址、可随机访问;字符设备不可寻址、按字符流顺序进出。最易混淆:把"块设备"等同于"按块传输"——本质是可寻址。

Q2: I/O 控制器为什么需要四类不同的寄存器?

数据、命令、状态是三类方向不同、时序不同的信息。数据双向流动,命令 CPU 单向下发,状态设备单向上报。合并会导致读写冲突,分设是清晰的职责分离。

Q3: 内存映像 I/O 用得更多,还是寄存器独立编址?

两者并存。x86 保留独立编址(IN/OUT),现代设备越来越多用内存映像 I/O(PCIe BAR 机制)。ARM 从设计之初仅支持内存映像 I/O。取决于 CPU 架构哲学与兼容性约束。

Q4: 状态寄存器的 1/0 含义是统一标准吗?

没有强制国际标准。主流约定 1=空闲、0=忙碌,特定设备可能有相反定义。驱动必须知道具体控制器的寄存器定义——这正是驱动必须针对具体硬件编写的原因。


总结

I/O 设备的三维分类体系和 I/O 控制器的寄存器架构构成了操作系统 I/O 管理的硬件基础。理解这些不是为了背诵,而是为后续掌握"为什么不同设备适用不同控制方式"——硬件特性决定了软件方案的选择空间。

📚 延伸阅读

  • Linux Kernel Documentation: Memory-Mapped I/O
  • 本系列第二篇:四种 I/O 控制方式(程序直接控制 / 中断驱动 / DMA / 通道控制)—— 即将发布
  • 本系列第三篇:I/O 软件层次结构 —— 即将发布
  • 本系列第四篇:SPOOLing 技术 —— 即将发布
  • 本系列第五篇:设备分配与缓冲区管理 —— 即将发布
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐