1. DMA 基础概念

1.1 DMA 工作原理

直接存储器访问(Direct Memory Access, DMA) 是一种允许硬件设备直接读写系统内存,而无需 CPU 逐字节参与的数据传输技术。DMA 控制器(DMA Controller)在总线架构中扮演“数据搬运工”的角色,将 CPU 从繁重的数据拷贝任务中解放出来。

核心思想:DMA 传输期间,CPU 只需初始化传输参数(源地址、目的地址、传输长度),然后即可执行其他计算任务;传输完成后 DMA 控制器通过中断通知 CPU。

DMA 传输的基本流程包含以下步骤:

  1. CPU 配置 DMA 控制器:设置源地址寄存器、目的地址寄存器、传输字节数、传输方向(内存→设备 / 设备→内存)。
  2. CPU 启动传输:向 DMA 控制器的“启动”位写 1,DMA 控制器获得总线控制权。
  3. DMA 控制器驱动总线:在时钟周期内,从源地址读取数据,写入目的地址,同时递减计数器。
  4. 传输完成中断:当计数器归零,DMA 控制器向 CPU 发送中断信号,CPU 处理后续数据。
DMA 基本工作流程 CPU 配置 DMA 源/目的/长度/方向 CPU 启动传输 写启动位 DMA 获得总线 总线仲裁 数据传输 源→目的 中断通知 CPU 传输完成 CPU 处理数据 中断服务例程 CPU 解放 DMA 传输期间 CPU 可 执行其他计算任务

1.2 DMA 在 PCIe 总线中的作用

在 PCI Express(PCIe)总线架构中,DMA 是高性能数据传输的核心机制。PCIe 设备(如网卡、NVMe SSD、GPU)通过 DMA 直接在系统内存和设备本地缓冲区之间搬运数据,避免数据经过 CPU 的多次拷贝。

PCIe 总线上的 DMA 传输具有以下关键特征:

特征 说明 对性能的影响
Memory-Mapped I/O (MMIO) 设备通过 BAR 空间暴露控制寄存器,CPU 使用内存访问指令操作设备 控制路径延迟低,但数据路径仍依赖 DMA
Bus Master PCIe 设备作为总线主控发起 DMA 读写请求(Memory Read/Write TLP) 设备主动搬运数据,CPU 无需轮询
Scatter-Gather DMA 设备支持不连续物理内存的 DMA 传输,通过描述符链表管理 消除内存碎片限制,提高内存利用率
Peer-to-Peer DMA 两个 PCIe 设备之间直接 DMA,不经过主机内存 极低延迟,适用于 GPU 直通、存储加速
关键理解:PCIe 本质上是一个“数据包交换”网络。DMA 传输被封装为 Transaction Layer Packet (TLP),通过 PCIe 交换结构(Switch)路由到目标内存或设备。DMA 的效率直接决定了 PCIe 设备的吞吐能力。
PCIe DMA 系统架构 CPU 中断处理 系统内存 DMA 缓冲区 Root Complex 地址翻译 PCIe Switch TLP 路由 NVMe SSD DMA 引擎 网卡 DMA 引擎 DMA 数据流(设备→内存) 设备 DMA 引擎 → PCIe TLP → Switch → Root Complex → 系统内存缓冲区

1.3 DMA 与 CPU 内存访问的区别

理解 DMA 与 CPU 直接内存访问之间的差异,是掌握 DMA 寻址掩码配置的前提。下表从多个维度对比两种访问方式:

对比维度 CPU 内存访问 DMA 内存访问
发起者 CPU 核心(Load/Store 指令) PCIe 设备(Bus Master)
地址空间 虚拟地址 → MMU → 物理地址 设备 DMA 地址(总线地址)
数据路径 CPU 缓存 → 内存控制器 → DRAM 设备 → PCIe → Root Complex → 内存
CPU 占用 100% 占用,无法并行 仅初始化 + 中断处理,传输过程零占用
传输粒度 字节/字/双字(缓存行) 通常为 64 字节 ~ 4KB(TLP 最大载荷)
延迟 纳秒级(缓存命中) 微秒级(PCIe 往返 + 内存访问)
适用场景 小数据量、控制流、中断处理 大数据块、流式 I/O、零拷贝传输
常见误区:DMA 地址 ≠ 物理地址。设备看到的“DMA 地址”经过 IOMMU 或 SWIOTLB 翻译后才能映射到物理内存。如果 DMA 掩码配置不当,设备可能无法访问 64 位地址空间,导致分配失败或数据损坏。

从系统软件的角度看,CPU 访问内存和 DMA 访问内存的路径差异如下:

  • CPU 路径:虚拟地址 → TLB/页表 → 物理地址 → 缓存 → 内存控制器 → DRAM
  • DMA 路径:设备 DMA 地址 → IOMMU 翻译(可选)→ 物理地址 → 内存控制器 → DRAM

在 Linux 内核中,DMA 地址的分配与映射通过 dma_alloc_coherent() 或 dma_map_single() 等 API 完成,这些 API 内部会考虑设备的 DMA 掩码限制,确保分配的物理内存落在设备可寻址范围内。

CPU 访问 vs DMA 访问路径对比 CPU 内存访问路径 CPU 核心 MMU/TLB L1/L2 缓存 内存控制器 DMA 内存访问路径 PCIe 设备 IOMMU 内存控制器 DRAM 关键差异 CPU: 虚拟→物理 DMA: 总线地址→物理

1.4 小结

DMA 是 PCIe 设备实现高性能数据传输的基石。通过将数据搬运任务卸载给设备自身的 DMA 引擎,CPU 得以专注于控制逻辑和计算任务。理解 DMA 的工作原理、在 PCIe 总线中的角色以及与 CPU 内存访问的本质区别,为后续学习 pci_dma_set_mask() 寻址掩码配置奠定了必要的理论基础。