跳转至

总线、中断、DMA 与存储设备

I/O 的根本困难

设备种类多、速度跨度大、事件到达时间不可预测。CPU 不能为每种设备接一套专用指令和线路,也不应以纳秒级循环等待毫秒级设备。I/O 子系统通过统一接口、异步通知和批量搬运解耦双方。

设备控制器与内存映射 I/O

设备控制器把具体协议封装为少量寄存器:状态、命令和数据。内存映射 I/O 把这些寄存器放进物理地址空间,CPU 可用普通 load/store 访问。

这简化了 ISA,却不能把设备寄存器当普通内存优化:某次读取可能清除状态,写入顺序可能有意义,cache 和乱序执行必须受限制。

总线与互连

传统总线共享地址、数据和控制线:

  • 地址说明访问目标;
  • 数据线承载内容;
  • 控制线说明读写、大小、响应和错误;
  • 仲裁器决定多个主设备谁先使用互连。

共享总线简单,但设备增多后带宽和电气负载受限。现代片上网络和点到点链路提供更多并行通道,本质上仍需路由、流控、仲裁和顺序规则。

轮询:最简单的同步

CPU 反复读取状态寄存器:

while device_not_ready:
    read_status
transfer_one_item

轮询实现简单、响应时间可预测,适合事件极频繁或极短等待;若设备很慢,大量 CPU 周期被浪费。操作系统也会混合使用:低负载靠中断,高吞吐网络在一轮中断后批量轮询,减少频繁切换。

中断:设备主动通知

设备就绪后提出中断请求。处理器通常在可中断边界:

  1. 保存必要的当前执行位置和状态;
  2. 根据中断号找到处理程序;
  3. 提升或屏蔽相应优先级;
  4. 执行短小的中断服务例程;
  5. 恢复并继续原程序。

中断把等待时间还给 CPU,但有保存现场、流水线扰动和 cache 污染开销。中断合并可减少次数,却增加单个事件等待延迟。

中断与异常都改变控制流。区别在于异常通常由当前指令同步触发,中断来自外部并与当前指令异步。

DMA:让设备直接搬大块数据

若每个字节都由 CPU load 后再 store,CPU 会成为搬运工。DMA 控制器接收源地址、目的地址、长度与方向后,作为总线主设备直接在设备和内存间传输,完成后再中断 CPU。

DMA 的收益是降低指令开销并支持突发传输;代价包括:

  • 与 CPU 竞争内存带宽;
  • 需要固定、映射或描述缓冲区;
  • 非一致 DMA 系统中要清理或失效 cache;
  • 在支持 IOMMU 的系统中,需要正确限制设备可访问的地址,避免越权;缺少 IOMMU 时只能依赖总线防火墙、受信设备或其他平台机制,隔离能力通常更弱。

中断和 DMA 不是替代关系:DMA 搬数据,中断报告完成或错误。

HDD:机械运动主导延迟

硬盘访问包括寻道、旋转等待和传输:

\[ T_{disk}=T_{seek}+T_{rotation}+T_{transfer}+T_{controller}. \]

随机访问频繁移动磁头,延迟高;连续大块读写摊薄机械开销,带宽更好。调度器会合并与排序请求,但过度排序可能损害公平性和请求时延。

SSD:没有磁头,但并非“无限快内存”

NAND flash 按页读写、按更大的擦除块擦除,且单元擦写次数有限。闪存转换层(FTL)把逻辑块地址映射到物理页,通过异地写、垃圾回收和磨损均衡管理介质。

因此 SSD 仍有特性:

  • 读通常快于写,擦除最慢;
  • 随机小写会触发写放大;
  • 空闲空间和 TRIM 有助于垃圾回收;
  • 多通道并行提高带宽,队列深度影响利用率;
  • 尾延迟会因回收和磨损均衡波动。

外设访问的完整例子

网卡接收一帧时,可先用 DMA 把数据写入驱动准备的内存环形缓冲区,再更新完成描述符并触发中断。驱动确认描述符、把数据交给网络栈,并补充新缓冲区。这里同时出现设备寄存器、内存顺序、DMA、cache 一致性和中断。

自测

  1. 轮询和中断分别在哪类事件频率下更合适?
  2. DMA 为什么减少 CPU 指令,却不能减少内存带宽占用?
  3. HDD 与 SSD 随机访问代价的物理来源分别是什么?