核心 06-IO与设备管理 预计 20 分钟 kp-026

I/O 控制方式与驱动模型:轮询、中断、DMA 与 VFS

CPU 与设备交互有三种基本控制方式——轮询(忙等)、中断(事件驱动)、DMA(设备直搬内存),上层通过驱动程序与 VFS 统一接口屏蔽千差万别的硬件。

学习状态:

一句话定义

CPU 与设备交互有三种基本控制方式——轮询(忙等)、中断(事件驱动)、DMA(设备直搬内存),上层通过驱动程序与 VFS 统一接口屏蔽千差万别的硬件。

为什么重要

I/O 是操作系统"管理外部世界"的全部内容。三种控制方式的取舍贯穿一切性能设计:网卡高吞吐场景为什么回归轮询(DPDK)、NVMe 为什么要海量中断聚合、数据库为什么绕开页缓存直写设备。理解它们,kp-028 的 I/O 模型演进才有因果链。

前置知识

kp-002(中断控制器与 DMA 的硬件机制)。

核心概念

  • 轮询(programmed I/O):CPU 反复读设备状态寄存器,简单、延迟低、纯浪费 CPU。
  • 中断驱动:设备就绪时发中断,CPU 现场被保存后执行处理程序。
  • 中断下半部:上半部(硬中断,越短越好)登记数据即返回,耗时工作推迟到 softirq/工作队列。
  • DMA:控制器自主搬运,CPU 只参与设置与收尾。
  • 设备控制器与寄存器:状态/命令/数据寄存器,端口 I/O 或内存映射(MMIO)访问。
  • 驱动程序(driver):内核中按总线枚举、以统一操作表注册的硬件专用代码。
  • VFS 与字符/块设备:一切设备在文件树上有节点,读写走统一系统调用。

原理与机制

三种方式的适用矩阵:

方式CPU 占用延迟适用
轮询100% 忙等最低高吞吐包处理(DPDK)、自旋短等待
中断事件触发中(切换开销)通用低速设备、键盘
中断+DMA极低中磁盘、网卡、显卡大块传输

一次磁盘读的中断式流程:驱动下发命令(写命令寄存器)→ 设置 DMA 描述符 → 睡眠等待 → 设备搬完数据发中断 → 上半部确认中断、登记完成 → 下半部唤醒等待进程。上半部/下半部分离是中断工程的灵魂:硬中断处理里若做重活,中断会被长时间屏蔽,系统整体延迟劣化。

VFS 的统一:open/read/write/close 背后是一张 file_operations 操作表——ext4 的读写指向页缓存逻辑,串口的读写指向驱动收发函数,应用层完全无感。这就是"一切皆文件"的工程兑现。

图示

PIO 路径:  CPU <--状态寄存器轮询--> 设备   CPU 全程守候
中断+DMA:  CPU 设置 -> 设备 --DMA--> 内存 ; 完成 -> 中断 -> CPU 收尾
           CPU 期间可运行其他进程

直观类比

轮询像站在门口每秒看一次信箱;中断像留了门铃;DMA 则像快递员直接进储藏室上架,只在搬完时按一次门铃。上半部/下半部像前台只签收包裹(硬中断),拆包入库交给后台仓管(工作队列)。

实例或案例

cat /proc/interrupts        # 各 CPU 核的中断计数与设备分布(含中断亲和)
watch -n1 'cat /proc/interrupts | grep eth0'   # 观察网卡中断风暴
lspci -k                    # 设备与正在使用的驱动
udevadm info /dev/sda       # 设备的 udev 属性(设备模型的用户态面)
ethtool -S eth0 | head      # 网卡计数器, 可见中断聚合与丢包

高吞吐观察:小包 flood ping 时 cat /proc/interrupts 中网卡中断线性飙升——这正是 NAPI 采用"中断 + 轮询混合"(首包中断后转轮询收包)的动机。

常见误区

  • 认为中断永远优于轮询:每秒百万包时每包一次中断的切换成本吞掉全部算力,高性能网络以受控轮询为正解。
  • 在中断处理程序里做耗时操作或睡眠:硬中断上下文禁止睡眠,且会屏蔽同级中断,重活必须推迟到下半部。
  • 认为驱动必然在内核态:用户态驱动框架(UIO、DPDK、VFIO)把设备直接映射给应用,是现代高性能 I/O 的主流路径之一。

与其他知识点的关系

DMA 与页的配合连接 kp-017( bounce buffer 与对齐);中断上下文不可睡眠约束了 kp-012 内核自旋锁的使用场景;请求队列的中断唤醒是 kp-013 的实例。

延伸阅读

《现代操作系统》I/O 章;《Linux 设备驱动程序》(LDD3,虽旧但上半/下半部模型讲得最透)。

自测题

  1. 为什么中断处理要分上半部与下半部?

答:硬中断需尽快返回以恢复系统响应性,上半部只做确认与登记,耗时处理推迟到可调度、可睡眠的下半部执行。

  1. 什么场景应该选轮询?

答:事件到达率高且持续(高吞吐包处理)时,轮询省掉每事件的中断切换成本,代价是占满一个核——用专用核换延迟与吞吐。

  1. VFS 解决什么问题?

答:为 ext4、NFS、procfs、设备节点等异构实现提供统一的 open/read/write 接口,使"一切皆文件"成为应用可依赖的稳定契约。

标签:#IO控制 #中断 #轮询 #驱动 #VFS #DMA