1. DMA 基础概念
1.1 DMA 定义
DMA(Direct Memory Access,直接存储器访问) 是一种允许硬件设备(如网卡、磁盘控制器、GPU)直接与系统内存交换数据,而无需 CPU 逐字节参与的 I/O 技术。DMA 控制器(DMAC)作为独立的总线主控设备,在系统总线上与 CPU 并行工作,完成数据块的高速搬运。
核心要点: DMA 的本质是“CPU 授权,硬件自治”。CPU 只需设置源地址、目的地址、传输长度和方向,DMA 控制器即可独立完成剩余操作,并在传输结束后通过中断通知 CPU。
1.2 DMA 与 CPU 数据搬运对比
传统 PIO(Programmed I/O)模式下,CPU 必须亲自执行每一条加载/存储指令来搬运数据;而 DMA 模式下,CPU 仅参与初始化与收尾。下表从多个维度对比两种方式:
| 对比维度 | PIO(CPU 搬运) | DMA 搬运 |
|---|---|---|
| CPU 占用率 | 高(100% 占用直到传输完成) | 低(仅初始化 + 中断处理,约 1-5%) |
| 吞吐量 | 受限于 CPU 主频与指令吞吐 | 接近总线带宽上限(如 PCIe Gen4 x16 约 32 GB/s) |
| 延迟 | 单字节延迟低,但大块传输累积延迟高 | 启动延迟略高(约 1-2 μs),但块传输延迟极低 |
| 适用数据量 | 小数据(< 64 字节,如寄存器读写) | 大数据(≥ 512 字节,如网络帧、磁盘块) |
| 硬件复杂度 | 无需额外控制器 | 需要 DMAC 或设备内置 DMA 引擎 |
| Cache 一致性 | 天然一致(CPU 直接访问) | 需软件或硬件维护一致性(如 cache 刷新/无效化) |
性能量化参考: 在 2.5 GHz 的 x86 CPU 上,PIO 搬运 1 MB 数据约需 500 μs(含循环开销),而 DMA 搬运同样数据仅需约 10 μs(PCIe 延迟 + 传输时间),性能提升约 50 倍。
1.3 DMA 传输优势与适用场景
DMA 的核心优势可归纳为以下四点:
- CPU 卸载: 将 CPU 从繁重的数据搬运中解放出来,使其专注于协议处理、计算和控制逻辑。
- 高吞吐: 利用总线突发传输(burst transfer)模式,单次 DMA 请求可传输多个数据字,充分利用总线带宽。
- 低延迟: 硬件级流水线操作,无需软件循环和中断上下文切换。
- 并行性: DMA 传输与 CPU 执行指令可完全重叠(overlap),实现真正的并行处理。
典型适用场景包括:
| 场景 | 说明 | 典型数据量 |
|---|---|---|
| 网络数据收发 | 网卡 RX/TX 描述符环 + DMA 直接将帧写入/读出内存 | 64 B ~ 9 KB(Jumbo Frame) |
| 存储 I/O | NVMe / AHCI 控制器通过 DMA 在内存与磁盘间搬运扇区 | 512 B ~ 2 MB |
| GPU 显存传输 | PCIe DMA 引擎在主机内存与显存之间搬运纹理/顶点数据 | 1 MB ~ 数 GB |
| 多媒体采集 | 摄像头/采集卡通过 DMA 将视频帧直接送入内存缓冲区 | 数百 KB ~ 数十 MB |
| 高速数据采集 | ADC/DAC 设备通过 DMA 连续传输采样数据 | 持续流,无固定块大小 |
1.4 DMA 传输基本流程(内联 SVG)
下图展示了一次典型 DMA 传输的完整生命周期,从 CPU 初始化到传输完成中断:
1.5 DMA 传输模式分类
根据总线控制权的管理方式,DMA 分为以下三种模式:
- 块传输(Block Transfer): DMAC 获得总线控制权后,连续传输整个数据块,传输期间 CPU 无法访问总线。适用于高速、大批量数据传输。
- 周期窃取(Cycle Stealing): DMAC 在每个总线周期中“窃取”一个时钟周期进行传输,然后释放总线。适用于中等速率设备,对 CPU 影响较小。
- 透明传输(Transparent Transfer): DMAC 仅在 CPU 不使用总线时(如 CPU 执行内部操作)进行传输。对 CPU 性能影响最小,但硬件实现复杂。
工程注意: 在 Linux 网络驱动中,块传输是最常用的模式。网卡 DMA 引擎通过描述符环(Descriptor Ring)管理多个数据缓冲区的链式传输,实现零拷贝(Zero-Copy)收发包。周期窃取模式多见于低速嵌入式系统,透明传输则较少使用。
1.6 DMA 地址空间与一致性
DMA 操作涉及三种地址空间:
| 地址类型 | 说明 | 示例 |
|---|---|---|
| CPU 虚拟地址 | 内核/用户态软件使用的地址 | 0xffff8881a2b3c000 |
| CPU 物理地址 | 内存总线上的真实物理地址 | 0x1a2b3c000 |
| DMA 总线地址 | 设备侧看到的地址(经 IOMMU 映射) | 0x10000000 |
在启用 IOMMU(如 Intel VT-d、AMD IOMMU)的系统中,DMA 总线地址与 CPU 物理地址可能不同。驱动必须使用 dma_alloc_coherent() 或 dma_map_single() 等 API 进行地址转换和一致性管理。
一致性模型:
- 一致性 DMA(Coherent DMA): 硬件保证 cache 与内存一致性,适用于小数据量、频繁访问的场景(如描述符环)。
- 流式 DMA(Streaming DMA): 软件通过 cache 刷新/无效化维护一致性,适用于大数据块传输(如网络帧数据)。
1.7 小结
DMA 是现代高性能设备驱动的基石。通过将数据搬运任务从 CPU 卸载到专用硬件控制器,DMA 实现了:
- CPU 利用率从 100% 降至 1-5%
- 吞吐量提升 10-50 倍(取决于总线带宽)
- CPU 与 I/O 的并行执行