5.1 I/O 系统基本概念

I/O 系统
包括 I/O 设备、设备控制器、I/O 通道(大型机)、I/O 软件等。I/O 管理的目标是方便性、效率、设备独立性。

I/O 设备按使用特性分类:

I/O 设备按信息传输单位分类:

I/O 控制方式

I/O 控制方式的发展目标是减少 CPU 对 I/O 的干预,提高 CPU 与 I/O 设备的并行程度。共有四种控制方式:

控制方式CPU 干预程度数据传输单位特点
程序查询方式高(轮询等待)CPU 全程等待,效率最低
程序中断方式中(中断时干预)CPU 与 I/O 并行,但每字需中断
DMA 方式低(开始/结束干预)DMA 控制器直接控制内存交换
通道方式最低一组块通道是专用处理器,CPU 仅需一条 I/O 指令

1. 程序查询方式

CPU 不断轮询设备状态寄存器,判断 I/O 是否完成。CPU 与 I/O 串行工作,效率最低,仅适用于简单、低速设备。

2. 程序中断方式

CPU 发出 I/O 命令后继续执行其他任务;设备完成 I/O 后向 CPU 发中断信号;CPU 响应中断,执行中断服务程序完成数据传输。

3. DMA 方式 (Direct Memory Access)

DMA 方式
直接存储器存取。在 DMA 控制器 (DMAC) 控制下,外设与内存之间直接交换数据,不经过 CPU。数据传输以为单位,整块传输完成后才中断 CPU 一次。

DMA 的工作过程:

DMA 与中断方式的区别:

对比项中断方式DMA 方式
中断触发每传输一个字整块传输完
数据传输经 CPU 寄存器中转外设↔内存直接交换
传输单位块(连续多个字)
CPU 干预每次中断都需 CPU仅开始和结束
适用设备中低速高速块设备
周期窃取:DMA 传输时,DMAC 与 CPU 共享内存总线。当 DMAC 需访存时,借用一个或多个存储周期,CPU 暂停。这种"窃取"不影响 CPU 计数器状态,称为周期窃取CPU 停机访问

交互式动画 · DMA工作流程

DMA控制器独立完成数据传送,只需在开始和结束时中断CPU。步进观察完整流程。

4. 通道方式

通道 (Channel)
独立于 CPU 的专用 I/O 处理器,能执行通道程序。CPU 只需发出一条 I/O 指令启动通道,通道即可独立完成一组数据块的 I/O 操作,结束后中断 CPU。

通道分为三类:

5.2 SPOOLing 技术

SPOOLing (Simultaneous Peripheral Operations On-Line)
假脱机技术。利用高速磁盘模拟独占设备,将独占设备改造为共享设备。核心思想:用磁盘作为中介,使 I/O 操作与 CPU 计算并行。

SPOOLing 系统的组成:

SPOOLing 的典型应用——共享打印机:

SPOOLing 特点:① 提高了 I/O 速度(从低速设备→高速磁盘);② 将独占设备改造为共享设备;③ 实现了虚拟设备功能。但 SPOOLing 本身不能加速单次 I/O,也不能缩短单道作业的执行时间。

5.3 缓冲区管理

引入缓冲的目的是:缓和 CPU 与 I/O 设备速度不匹配的矛盾;减少对 CPU 的中断频率;提高 CPU 与 I/O 设备的并行性。

1. 单缓冲 (Single Buffer)

系统在主存中为每个 I/O 操作分配一个缓冲区。设备先将数据送入缓冲区,CPU 从缓冲区取数据处理。两者交替使用同一个缓冲区。

单缓冲处理时间:设 T 为设备输入一块的时间,C 为 CPU 处理一块的时间。则处理一块的时间 ≈ max(T, C) + M(M 为缓冲区到工作区的移动时间)。当 M 可忽略时为 max(T, C)。

2. 双缓冲 (Double Buffer)

分配两个缓冲区。设备向一个缓冲区输入数据的同时,CPU 可从另一个缓冲区取数据处理。两者可并行工作。

双缓冲处理时间:若 C < T,处理一块的时间 ≈ T;若 C > T,处理一块的时间 ≈ C。当 C ≈ T 时,CPU 与设备高度并行。双缓冲可使 CPU 与设备并行度显著提升。

3. 循环缓冲 (Circular Buffer)

多个缓冲区组成循环队列。生产者指针 (in) 和消费者指针 (out) 分别指向下一个可写入和可读取的位置。适合输入输出速度不匹配的场合。

4. 缓冲池 (Buffer Pool)

多个缓冲区组成公用缓冲池,可供多个进程共享。缓冲池中的缓冲区按状态分为:空缓冲队列、输入队列、输出队列。既可用于输入也可用于输出,利用率高。

缓冲策略缓冲区数并行程度适用场景
单缓冲1简单 I/O
双缓冲2CPU 与设备速度接近
循环缓冲多个较高生产者-消费者
缓冲池多个(共享)多进程并发 I/O

缓冲区管理伪代码

// 单缓冲:CPU 与设备串行使用同一个缓冲区
void SingleBuffer_IO(){
  while(true){
    device_read(buffer);        // 设备写入缓冲区
    cpu_process(buffer);       CPU 从缓冲区读取处理
    // 二者串行:max(T,C)+M
  }
}

// 双缓冲:CPU 与设备并行
void DoubleBuffer_IO(){
  int buf[2];
  int in = 0, out = 1;
  device_read(buf[in]);          // 先装满 buf[0]
  while(true){
    par {                               // 并行执行
      device_read(buf[in]);    // 设备向 buf[in] 写入
      cpu_process(buf[out]);   CPU 从 buf[out] 读取
    }
    in = 1-in; out = 1-out;  // 交换
  }
}

// 循环缓冲:in/out 指针环形使用
const int N = 10;              // 缓冲区数量
Buffer ring[N];
int in = 0, out = 0, count = 0;

void Producer(){
  while(true){
    if(count == N) sleep();     // 缓冲区满
    ring[in] = produce();
    in = (in+1) % N;
    count++;
  }
}

void Consumer(){
  while(true){
    if(count == 0) sleep();  // 缓冲区空
    data = ring[out];
    out = (out+1) % N;
    count--;
    consume(data);
  }
}

5.4 设备分配与回收

设备分配的数据结构:

设备分配方式:静态分配(作业级,运行期间独占,利用率低)和动态分配(进程级,按需申请释放)。设备独立性:用户使用逻辑设备名申请,系统通过 LUT 映射到物理设备。

5.5 I/O 软件层次结构

I/O 软件采用分层设计,每层利用下层提供的服务实现新功能,向上层屏蔽下层细节。从低到高分四层:

层次名称主要功能与硬件相关性
① 最低层中断处理程序响应 I/O 中断,唤醒等待的驱动程序,处理中断返回直接相关
② 次低层设备驱动程序将上层抽象的 I/O 请求转化为具体设备控制指令,驱动设备工作直接相关
③ 中间层设备无关 I/O 软件提供统一接口(read/write/open)、缓冲管理、设备分配、错误报告、独占设备的分配与释放无关
④ 最高层用户层 I/O 软件提供系统调用接口(如 C 库的 printf 调用 write 系统调用)、SPOOLing 假脱机技术无关
关键区分:①与②与硬件直接相关(设备相关),换设备需修改;③与④与硬件无关(设备无关),提供统一接口。408 高频考点:设备驱动程序向下直接与硬件交互;设备无关软件提供缓冲管理和设备分配。

I/O 请求处理流程

I/O 应用程序接口

操作系统为应用程序提供了一组标准化的 I/O 接口,屏蔽底层设备的差异。按设备类型分类:

1. 字符设备接口

字符设备以字节流的形式访问,不支持随机寻址。典型接口:open、read、write、close。常见字符设备:键盘、鼠标、串口、终端。字符设备通常以流的方式顺序访问,无块结构。

2. 块设备接口

块设备以固定大小数据块为单位访问,支持随机寻址。典型接口:open、read、write、seek、ioctl。常见块设备:磁盘、SSD。块设备支持随机读写任意位置的数据块,OS 通过缓冲区/页缓存优化块设备的访问。

3. 网络设备接口 (Socket)

网络设备通过 Socket(套接字)接口访问,不同于传统的 read/write 模型。典型接口:socket、bind、listen、connect、accept、send、recv。网络通信使用报文而非字节流/块。

阻塞 I/O vs 非阻塞 I/O

类型行为特点
阻塞 I/O进程发出 I/O 请求后,若数据未就绪则该进程挂起等待,直到数据准备好才返回编程简单,进程被阻塞期间 CPU 可调度其他进程
非阻塞 I/O进程发出 I/O 请求后,若数据未就绪则立即返回一个错误码(如 EWOULDBLOCK),进程可继续执行或轮询重试不阻塞进程,但需反复轮询(忙等),CPU 利用率低

同步 I/O vs 异步 I/O

类型行为特点
同步 I/O (Synchronous)进程发起 I/O 请求后,必须等待 I/O 操作完成(数据已从内核拷贝到用户空间)才能继续执行包括阻塞 I/O、非阻塞 I/O、I/O 多路复用(select/poll/epoll)
异步 I/O (Asynchronous)进程发起 I/O 请求后立即返回,内核在后台完成整个 I/O(包括数据拷贝到用户空间),然后通知进程真正不阻塞,进程无需等待任何 I/O 阶段(如 Linux AIO、io_uring)
关键区别:同步 I/O 中进程"发起请求→等待→数据就绪";异步 I/O 中进程"发起请求→立即返回→内核负责完成 I/O→回调/信号通知"。I/O 多路复用(select/poll/epoll)是同步的——进程仍需等待数据从内核空间拷贝到用户空间。

5.6 固态硬盘 SSD [22新增]

固态硬盘 (Solid State Drive, SSD)
基于闪存(NAND Flash)芯片的存储设备,通过电子方式读写数据,无机械部件(无盘片、无磁头、无电机),因此访问延迟远低于传统 HDD。

SSD 结构

SSD 主要由两大部分组成:

SSD 读写特性

特性说明
读快写慢读取延迟约 0.05~0.1ms;写入延迟约 0.1~1ms。读取远快于写入,原因是写入可能涉及擦除、编程和垃圾回收。
写前擦除 (Erase-before-Write)闪存的物理特性:不能直接覆盖写入。必须先擦除整个块(设置为全 1),才能将数据编程写入。读/写以页为单位,擦除以块为单位。
无寻道时间没有磁头移动和盘片旋转,访问任意位置的时间几乎一致,随机访问性能远超 HDD
有限擦写次数 (P/E Cycles)每个闪存块的可擦写次数有限(SLC ~10 万次,MLC ~1 万次,TLC ~3000 次,QLC ~1000 次),超出后块会失效。

磨损均衡 (Wear Leveling)

为延长 SSD 寿命,控制器通过 FTL 实现磨损均衡,使所有块的擦写次数均匀分布:

垃圾回收 (Garbage Collection, GC)

由于写前擦除的特性,当需要擦除一个块时,该块中可能仍包含有效数据(未被删除/更新的页)。GC 过程:

SSD vs HDD 对比

对比项HDD (机械硬盘)SSD (固态硬盘)
结构盘片+磁头+电机(机械)闪存芯片+控制器(电子)
随机读延迟~5-10ms(含寻道+旋转)~0.05-0.1ms
随机写延迟~5-10ms~0.1-1ms(受 GC 影响)
顺序读/写速度~150-250 MB/s~500-7000 MB/s
抗震性差(机械部件脆弱)好(无机械部件)
寿命无固定写入限制有限擦写次数(P/E Cycles)
价格/容量比高(但持续下降)
磁盘调度需要(优化寻道)不需要——随机访问时间均一
408 考点:理解 SSD 写前擦除特性、磨损均衡的目的、GC 与写放大的关系;SSD 不需要磁盘调度算法(无寻道延迟);区分动态 vs 静态磨损均衡。