DMA 转移的是载荷搬运工作,不是全部控制责任;地址映射、缓冲区所有权、可见性、完成与回收缺一不可。

CPU 不逐字节搬运,仍参与全过程

应用提出需求,内核与驱动组织缓冲区和设备任务,设备按照协议访问内存,软件再处理结果。DMA 并不取消 CPU 的提交、权限检查和完成处理,也不保证零复制。

把一个 I/O 请求看成“命令、载荷、通知”三件事,会更容易理解:CPU 可能处理很小的命令描述,设备搬运很大的载荷,最终只返回一个状态。不同设备的队列、描述符格式与通知方法不相同。

三种地址不能替换

CPU 虚拟地址、系统物理地址、设备 DMA 地址具有不同含义。Linux DMA API 负责连接驱动所用缓冲区和设备可访问地址;平台可能涉及 IOMMU 或其他适配。驱动不能自行假定 DMA 地址等于物理地址。依据:DMA API

CPU虚拟地址 --> CPU地址翻译 --> 系统物理页
                                      ^
                                      |
设备DMA地址 --> IOMMU/平台映射 --------+

图描述地址语义,不保证某平台启用 IOMMU,也不表示所有设备使用同一种映射。

所有权是一条时间线

缓冲区分配后,软件先准备内容和描述;设备拥有执行所需的访问权限后开始搬运;设备报告结束,软件确认相应范围已可消费,随后复用或释放缓冲区。

原创状态模型:

软件准备 -> 发布给设备 -> 设备使用 -> 完成被确认 -> 软件回收
              |              |
          不可提前复用    不可提前释放

若驱动超时后直接释放仍被设备使用的内存,迟到的 DMA 可能破坏其他对象。超时是软件停止等待,不自动等于设备已停止访问。恢复协议必须解决这一时间差。

一致性映射与流式映射

Linux 区分不同 DMA 映射用法。流式映射的方向与同步调用表达访问交接;一致性映射也不能免除所有顺序要求。依据:DMA mapping guide

这里关键是区分两件事:双方是否看到相应数据;描述与通知是否按正确顺序生效。第一件事解决可见性,第二件事解决排序。把“硬件一致性”当作“所有读写自动有序”会遗漏协议边界。

Scatter-gather 与缓冲区约束

上层内容可能分散在多个内存范围,驱动和设备可以通过相应接口组织传输。映射成功后的设备段数、长度、对齐与地址能力均受接口约束,不能从一个连续虚拟缓冲区推导设备只需一个连续地址。

这也解释了为什么应用的读取大小、块层请求和设备任务数量可能不同。拆分、合并和映射改变的是执行形式,不是应用逻辑对象。

完成、轮询与中断

设备可以把状态写入完成结构,由软件轮询或由中断提示处理。中断到达不意味着应用线程立即运行;还有处理上下文和调度阶段。详见 中断与完成。

正确理解 DMA 后,网络收发和存储读写不再是黑盒:问题可以定位到任务准备、地址映射、设备执行、完成通知或资源回收,而不是笼统地说“硬件没响应”。


服务器知识库 · 系统架构 · 数据路径 · 测试验收 · 工程参考

公开资料核对:2026-10-07。文档类型:Explanation。逻辑图、场景推演与报告模板为原创,不代表实测结果、厂商内部设计或公司制度;操作仅限获授权的目标和环境。