2. DMA 基础概念:DMA 工作原理、总线主控与从控、DMA 传输方向

DMA(Direct Memory Access,直接存储器访问)是 PCIe 设备实现高性能数据传输的核心机制。在 PCIe 驱动开发中,理解 DMA 的工作原理、总线主控/从控角色以及传输方向,是正确配置地址映射和处理中断的前提。本节将系统梳理这些基础概念,并通过 SVG 图例和表格进行对比说明。

2.1 DMA 工作原理

DMA 允许外设(如网卡、存储控制器、GPU)绕过 CPU,直接在系统内存与设备之间传输数据。其核心思想是:CPU 只需发起传输任务,而实际的搬运工作由 DMA 控制器或支持总线主控的 PCIe 设备完成,从而释放 CPU 去处理其他计算任务。

关键优势: 降低 CPU 占用率,提升系统吞吐量,尤其适合大数据块传输(如网络包、磁盘 I/O)。

典型的 DMA 传输流程如下:

  1. CPU 准备缓冲区: 驱动程序在系统内存中分配 DMA 缓冲区,并将物理地址(或 IOMMU 转换后的地址)写入设备寄存器。
  2. CPU 发起传输: 驱动程序通过写设备控制寄存器(如门铃寄存器)通知设备开始 DMA 操作。
  3. 设备执行传输: PCIe 设备作为总线主控,通过 PCIe 总线直接读写系统内存,无需 CPU 逐字节搬运。
  4. 传输完成通知: 设备通过 MSI/MSI-X 中断或传统 INTx 中断通知 CPU 传输完成。
  5. CPU 处理数据: 中断服务例程(ISR)检查传输状态,处理已完成的数据缓冲区。
注意: 在支持 IOMMU(如 Intel VT-d、AMD-Vi)的系统中,设备看到的地址是 IOVA(I/O Virtual Address),而非物理地址。驱动必须使用 DMA API(如 dma_map_single)进行地址转换。
DMA 传输工作流程 CPU / 驱动 DMA 缓冲区 PCIe 设备 中断控制器 ① 分配/映射 ② 写门铃寄存器 ③ DMA 数据传输(总线主控) ④ 中断请求 ⑤ CPU 执行 ISR 说明: CPU 仅参与传输的发起和完成通知,实际数据搬运由 PCIe 设备通过总线主控完成。 步骤③中,设备直接读写系统内存,无需 CPU 逐字节拷贝。

2.2 总线主控与总线从控

在 PCIe 体系中,设备根据其能否主动发起总线事务,分为两种角色:

角色 定义 典型设备 DMA 能力
总线主控(Bus Master) 能够主动发起 PCIe 存储器读写、I/O 读写或配置读写事务的设备。 网卡、NVMe SSD、GPU、RAID 控制器 支持 DMA,可自主访问系统内存
总线从控(Bus Slave / Target) 只能被动响应总线主控发起的事务,不能主动发起事务。 传统 UART、GPIO 控制器、低速传感器 不支持 DMA,依赖 CPU 或 DMA 控制器搬运数据
驱动开发要点: 在 PCIe 驱动中,要使能设备的总线主控能力,必须在初始化时设置 PCI 命令寄存器中的“Bus Master Enable”位(bit 2)。否则,即使设备硬件支持 DMA,也无法发起任何存储器事务。

总线主控与从控的交互关系如下图所示:

总线主控与从控交互 总线主控 (主动发起事务) 系统内存 (从控) PCIe 从设备 (从控) DMA 写(MemWr) DMA 读(MemRd) 配置/IO 读写 总线主控可以同时与多个从控通信;从控不能主动发起事务,只能响应主控的请求。

2.3 DMA 传输方向

DMA 传输方向决定了数据在设备与系统内存之间的流动路径。在驱动开发中,正确设置传输方向是保证数据一致性和避免缓存问题的关键。

传输方向 描述 典型场景 驱动 API 方向标志
设备到内存(DMA 读) 设备从内部缓冲区读取数据,写入系统内存。 网卡接收数据包、磁盘读取数据 DMA_FROM_DEVICE
内存到设备(DMA 写) 设备从系统内存读取数据,写入设备内部缓冲区。 网卡发送数据包、磁盘写入数据 DMA_TO_DEVICE
双向传输(Bidirectional) 设备与内存之间可双向传输,通常用于控制/状态同步。 GPU 纹理上传/下载、FPGA 数据交换 DMA_BIDIRECTIONAL
重要提示: 方向标志影响 DMA API 的缓存一致性操作。例如,dma_map_single(dev, cpu_addr, size, DMA_FROM_DEVICE) 会在传输前刷新 CPU 缓存,确保设备写入的数据不会被 CPU 缓存污染。使用错误的方向标志可能导致数据损坏。
DMA 传输方向示意图 系统内存 (DMA 缓冲区) CPU 地址空间 PCIe 设备 (内部 FIFO/缓冲区) 设备地址空间 DMA_FROM_DEVICE 设备写入内存(接收) DMA_TO_DEVICE 设备读取内存(发送) DMA_BIDIRECTIONAL 双向同步(如 GPU 数据交换) 驱动注意事项: 方向标志影响 dma_map/unmap 时的缓存同步操作。 错误的方向可能导致数据不一致或性能下降。

2.4 总结与对比

下表汇总了 DMA 基础概念的核心要点,便于快速回顾:

概念 核心要点 驱动关注点
DMA 工作原理 设备直接访问内存,CPU 仅负责发起和完成处理 使用 DMA API 进行地址映射和同步
总线主控 设备主动发起 PCIe 事务,是 DMA 的前提 必须设置 PCI 命令寄存器的 Bus Master Enable 位
总线从控 设备只能被动响应,不能主动发起事务 不支持 DMA,通常用于控制/状态寄存器访问
DMA 传输方向 决定数据流方向,影响缓存一致性策略 使用正确的 DMA_FROM_DEVICE / DMA_TO_DEVICE / DMA_BIDIRECTIONAL