查询、中断与 DMA
复习
- 写时复制:先共享页面,真正修改时再复制
- 内存分配与碎片:操作系统怎样切分、回收和整理内存
- 设备控制器与驱动程序:用统一接口隐藏硬件差异
TL;DR
- CPU 与设备交换数据,有三种方式:程序查询、中断、DMA
- 程序查询:CPU 反复问设备好了没,最笨也最浪费
- 中断:设备好了主动通知 CPU
- DMA:让设备直接和内存搬数据,几乎不用 CPU 插手
正文
上一章解决了“怎么对设备说话”。可一次数据传输,CPU 到底要参与多少?这一章看三种越来越省事的方式。
程序查询:不停追问
最简单的方式叫程序查询(programmed I/O):CPU 把命令发给控制器,然后反复检查状态,等设备就绪,再一个字节一个字节地搬。
发命令 → 好了没?没好。好了没?没好。…… 好了 → 搬一个字节 → 再问
它实现简单,但 CPU 几乎所有时间都耗在“傻等 + 追问”上,效率极低。就像你站在打印机边上,一秒问一次“好了吗”,别的事什么都干不了。
中断:好了叫我
更聪明的办法是中断(interrupt):CPU 发完命令就去干别的事,等设备准备好了,主动“叫”一声(发中断),CPU 再回来处理。
- CPU 不再空等,可以把时间花在别的进程上
- 设备就绪时,打断 CPU,响应中断、搬数据
这已经比查询高效得多——CPU 的时间没有被浪费在追问上。不过,如果数据量很大,每搬一个字节就中断一次,频繁的“打断—恢复”本身也是不小的开销。
DMA:让设备自己去搬
数据量一大,连“每次中断”都嫌烦。于是有了直接存储器访问(DMA,Direct Memory Access):
- 先把“从哪搬、搬到哪、搬多少”告诉一个专门的 DMA 控制器
- 之后设备就和内存直接传输,不需要 CPU 参与每一个字节
- 整批传完,DMA 控制器再发一次中断通知 CPU
CPU:交给 DMA 控制器,我去忙别的
DMA 控制器:设备 ←→ 内存,批量搬……
搬完:中断通知 CPU
对比一下,CPU 的参与程度是逐步降低的:
| 方式 | CPU 参与 | 适合 |
|---|---|---|
| 程序查询 | 全程盯着 | 极简单的小设备 |
| 中断 | 每次就绪时参与 | 一般设备 |
| DMA | 只负责开头和结尾 | 大批量传输,如硬盘、网卡 |
一句话:从查询到中断再到 DMA,CPU 越来越省心。 谁也不想让珍贵的 CPU 去干“搬砖”的活。
思考题
既然 DMA 最省 CPU,为什么不是所有设备都用 DMA?对一个小键盘来说,用 DMA 值得吗?
小结
知识点
- 程序查询:CPU 反复检查设备状态,浪费严重
- 中断:设备就绪时主动通知 CPU
- DMA:设备与内存直接批量传输,CPU 只参与首尾
- 三种方式按数据量和设备特点选择
参考资料
- Wikipedia(zh):程序化输入输出:programmed I/O
- Wikipedia(zh):直接内存访问:DMA
思考题答案(仅供参考)
因为 DMA 需要专门的 DMA 控制器,还要占用总线、配置传输参数,本身是有成本的。对硬盘、网卡这种一次要搬成千上万字节、传输频繁的设备,摊下来很划算;可对键盘来说,一次往往只来一两个字节,用 DMA 就像“为寄一封信包一架飞机”,配置开销远大于收益,用中断反而更合适。所以选哪种方式,要看数据量和频率——工具没有最好,只有合适。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪