1. DMA 基础概念

1.1 DMA 工作原理

DMA(Direct Memory Access,直接存储器访问)是一种允许硬件子系统直接读写系统内存而无需 CPU 干预的数据传输技术。在 Linux 驱动开发中,DMA 是高性能外设(如网卡、存储控制器、音视频设备)实现高吞吐量数据传输的核心机制。

核心思想:DMA 控制器接管总线控制权,在源地址与目的地址之间建立一条独立于 CPU 的数据通道,传输过程完全由硬件状态机驱动。

一次典型的 DMA 传输包含以下阶段:

  1. 配置阶段:CPU 设置 DMA 控制器的源地址、目的地址、传输长度、传输方向(内存→外设 / 外设→内存 / 内存→内存)以及触发方式。
  2. 启动阶段:CPU 向 DMA 控制器写入启动命令,或由外设硬件请求信号(DMA Request)自动触发。
  3. 传输阶段:DMA 控制器逐字节或逐字搬运数据,每完成一个单元传输,地址寄存器自动递增,计数器递减。
  4. 完成阶段:当计数器归零,DMA 控制器向 CPU 发出中断信号(DMA Complete Interrupt),通知传输结束。
DMA 传输流程 CPU 配置 DMA 启动传输 DMA 搬运数据 传输完成中断 CPU 处理数据 CPU 仅在配置和 中断处理时参与

1.2 DMA 与 CPU 数据搬运对比

传统的数据搬运由 CPU 通过 PIO(Programmed I/O)模式逐字读写外设寄存器完成。DMA 与 PIO 在资源占用、传输速率和系统并发性上存在本质差异:

对比维度 CPU 搬运(PIO) DMA 搬运
总线控制权 CPU 全程占用总线 DMA 控制器暂用总线,CPU 可继续执行指令(缓存命中时)
每字节开销 多条指令(加载、存储、循环控制) 1 个总线时钟周期(硬件自动完成)
CPU 利用率 100% 被占用,无法处理其他任务 仅配置和中断阶段占用 CPU(通常 < 5%)
传输速率 受限于 CPU 主频和指令吞吐 接近总线理论带宽(如 PCIe Gen3 x4 约 4 GB/s)
适用数据量 小数据量(< 64 字节) 大数据量(≥ 256 字节,典型场景 KB ~ MB 级)
实时性 可预测,无额外延迟 需考虑总线仲裁延迟和中断响应延迟
经验法则:在嵌入式 Linux 驱动中,单次传输超过 256 字节时,DMA 的综合效率已显著优于 PIO。对于 SPI、I²C 等低速总线,PIO 仍可接受;对于 MMC、Ethernet、USB 3.0 等高速外设,DMA 是强制要求。

1.3 DMA 传输的优势与适用场景

核心优势

  • 解放 CPU:CPU 从繁重的数据搬运中解脱,专注于协议解析、算法计算和任务调度,提升系统整体吞吐量。
  • 低延迟高带宽:DMA 控制器直接操作总线,传输延迟仅取决于总线时钟和仲裁逻辑,远低于 CPU 中断驱动的 PIO 模式。
  • 支持后台传输:DMA 传输可与 CPU 执行指令并行进行(需缓存一致性机制配合),实现真正的流水线处理。
  • 减少中断频率:一次 DMA 传输可搬运大量数据,仅产生一次完成中断,而 PIO 模式下每传输一个字节或字都可能触发中断。

典型适用场景

场景 说明 典型传输量
网络数据收发 网卡 DMA 直接将网络帧写入内存 Ring Buffer,CPU 仅处理协议栈 64 B ~ 9 KB(Jumbo Frame)
存储设备读写 eMMC / NVMe / SD 卡使用 DMA 搬运扇区数据 512 B ~ 1 MB
音视频采集播放 摄像头传感器通过 DMA 将帧数据送入内存,GPU/VPU 直接消费 数百 KB ~ 数十 MB
高速数据采集 ADC / FPGA 通过 DMA 连续搬运采样数据到环形缓冲区 连续流,无固定包长
内存间批量拷贝 DMA 引擎(如 Intel QuickData)实现内存到内存的高速拷贝 任意大小,通常 ≥ 1 KB
DMA vs PIO 系统架构对比 PIO 模式(CPU 搬运) CPU 外设 内存 DMA 模式 CPU 外设 内存 DMA 控制器 CPU 全程参与,总线利用率低 DMA 控制器直接搬运,CPU 可并行工作
注意事项:DMA 并非万能方案。在以下情况应谨慎使用或避免 DMA:
• 传输数据量极小(< 64 字节),DMA 配置开销超过 PIO 开销;
• 系统缺乏硬件缓存一致性支持(如某些低端 MCU),DMA 与 CPU 共享数据时需手动 cache 刷新;
• 实时性要求极高且中断延迟不可控的场景(可考虑 polling DMA 或 PIO)。