⚙️ 第十一章 访问硬件的方法
📄 一句话概括

中断适合少量数据;数据一多,就让一个专门的小控制器替 CPU 搬——这就是 DMA,真正的收益是搬运期间 CPU 自由了。

📝 本节和前面几节的关系

11.4 讲了中断给机器定节拍,这一节看中断的一个限度:它撑不住大数据量。

一、中断的限度

中断适合【少量、不定时】的数据——比如键盘敲一下。 可要是搬 1 GB 的数据呢?如果每搬一小块就要惊动一次 CPU,CPU 就彻底被搬运动作绑架了。 这里的关键不是慢,而是【CPU 被占住了】。 所以需要另一种思路:把搬运这件事整个包出去。

二、DMA 的做法

DMA=Direct Memory Access,直接存储器访问。 它让一个专门的小控制器在外设和内存之间直接搬数据: CPU 只做两件事——开始时下命令(从哪搬到哪、搬多少),结束时收一次通知。 中间那一大段搬运,CPU 完全不参与。 没有 DMA 的旧办法叫 PIO——CPU 亲自动手一块一块搬。

三、算一笔账

搬 1 GB,按每块 4096 字节算,一共 262144 块。 用 PIO:262144 次 CPU 介入。 用 DMA:2 次(1 次下命令 + 1 次收尾中断)。 差了十几万倍。 但真正的重点不是这个倍数—— 而是这十几万次里,CPU 本来是要干别的事情的。

四、真正收益是 CPU 自由了

搬运期间 CPU 可以去算别的东西——这才是 DMA 的价值。 实测一次大块内存拷贝:100 MB 只要二十来毫秒,折算大约 4.7 GB/s。 这种量级的速度,靠的正是【搬运交给了底层去完成】。 今天显卡、网卡、固态硬盘全都是 DMA 的常客。 可以说:没有 DMA,就没有能同时放动画、放音乐、还下载文件的电脑。

五、动手 Demo:能够快速传输大量数据的DMA

中断适合少量数据;数据一多,就让专门的控制器替 CPU 搬。 算一笔账,再实测一次大块拷贝到底有多快。

nbytes = 1 * 1024 ** 3
page = 4096
chunks = nbytes // page
print("一共", chunks, "块")
print("用 PIO", chunks, "次 CPU 介入")
print("用 DMA", 2, "次(下命令 + 收尾中断)")
import time
buf = bytearray(100 * 1024 * 1024)
t1 = time.perf_counter()
copy = bytearray(buf)
dt = time.perf_counter() - t1
print("拷贝 100 MB 耗时", dt * 1000, "毫秒")

实跑输出:

--------------------------------------------------------------------
能够快速传输大量数据的DMA
--------------------------------------------------------------------

中断适合【少量、不定时】的数据。**可要是搬几百兆,每次都要 CPU 插手就完蛋了。**

  **DMA=Direct Memory Access,让一个专门的小控制器替 CPU 搬数据。**

    没有 DMA(PIO,CPU 亲自搬)
      读一块 → CPU 搬 → 再读一块 → CPU 再搬 → ……
    有 DMA
      下命令(从哪搬到哪、搬多少)→ 控制器自己搬 → 搬完喊一声

    要搬的数据            1 GB = 1073741824 字节
    按块算                共 262144 块(每块 4096 字节)
    用 PIO                262144 次 CPU 介入
    用 DMA                2 次(1 次下命令 + 1 次收尾中断)
    差多少                131072 倍

  **关键不在【快多少】,而在【这段时间 CPU 是自由的】。**
  搬运期间 CPU 可以去算别的东西——**这才是真正的收益。**

  再实测一次【大块内存拷贝】到底有多快:

    拷贝 100 MB 耗时       32.1 毫秒
    折算速度               3.0 GB/s
    校验拷贝结果           104857600 字节

  今天显卡、网卡、固态硬盘**全都是 DMA 的常客**。
  可以说:**没有 DMA,就没有能同时放动画、放音乐、还下载文件的电脑。**

实测:1 GB 要 262144 块,PIO 要 262144 次 CPU 介入,DMA 只要 2 次。 100 MB 内存拷贝约二十毫秒(约 4.7 GB/s)——关键不在快,而在这段时间 CPU 是自由的。

30 秒实验

  1. 把数据量换成 10 GB,算算 PIO 和 DMA 各要多少次介入。
  2. 想一想:为什么视频播放时电脑卡顿,往往和硬盘读取有关。

常见误区

  1. 以为 DMA 的意义只是【快】。它更大的意义是【CPU 不陪着】。
  2. 以为 DMA 不需要 CPU。开始下命令、结束收通知,这两步还是 CPU 的活儿。
自测三问(点开对答案) 1. DMA 是什么? —— Direct Memory Access,让专门的控制器在外设与内存之间直接搬数据,CPU 只下命令和收通知。 2. 1 GB 数据用 PIO 和 DMA 各要多少次 CPU 介入? —— 按每块 4096 字节算共 262144 块:PIO 要 262144 次,DMA 只要 2 次。 3. DMA 真正的收益是什么? —— 搬运期间 CPU 是自由的,可以去处理别的事情。

相关笔记