当前位置: 首页 > news >正文

深入 DMA:让外设绕过 CPU 与内存“私聊”的黑科技

当你从硬盘拷贝大文件时,CPU 是否全程忙碌?当网卡收到数据包时,是谁负责搬进内存?答案就是 DMA(Direct Memory Access,直接存储器访问)。今天,我们就来拆解这项让外设“零 CPU 干预”直接访问内存的底层技术。

在计算机体系结构中,CPU 并非万能。如果每次数据搬运都需要 CPU 亲自出马,那么系统性能将大打折扣——尤其是在高速外设(如 SSD、万兆网卡、GPU)场景下。DMA 技术正是为了解决这个瓶颈而生。本文将从原理、工作模式、控制器结构到现代演进,带你彻底搞懂 DMA。


一、为什么需要 DMA?

在没有 DMA 的老式系统中,外设与内存之间的数据传输流程如下(以读磁盘为例):

  1. CPU 发出读取指令。
  2. 磁盘控制器将数据读入内部缓冲区。
  3. 磁盘控制器向 CPU 发起中断,告知数据已准备好。
  4. CPU 将数据从磁盘缓冲区逐字节搬移到内存。
  5. 重复步骤 3-4 直到所有数据传输完成。

问题:整个过程 CPU 充当“搬运工”,无法执行其他任务,尤其对于大数据量传输,CPU 占用率极高,系统吞吐量大幅下降。

DMA 解决方案:引入DMA 控制器(DMAC),由它接管数据搬运工作。CPU 只需告诉 DMAC“从哪里来、到哪里去、搬多少”,然后继续执行其他任务。传输完成后,DMAC 再通知 CPU。


二、DMA 的工作原理

2.1 DMA 控制器结构

一个典型的 DMAC 包含以下寄存器:

寄存器作用
源地址寄存器(SAR)存放数据来源地址(内存或外设 I/O 接口)
目标地址寄存器(DAR)存放数据去向地址
字节计数寄存器(BCR)需要传输的字节数
控制/状态寄存器(CSR)控制传输方向、传输模式、中断使能,以及状态标志

此外,DMAC 内部有地址递增逻辑、总线请求/应答逻辑,以及用于临时缓存的数据缓冲器。

2.2 单字节传输与块传输

DMAC 支持两种基本传输模式:

  • 单字节传输(Cycle Steal):每次传输一个字节/字后,释放总线,让 CPU 或其他 DMA 设备使用。适用于速度较慢的外设。
  • 块传输(Burst Mode):DMAC 获得总线控制权后,连续传输整个数据块,期间不释放总线。适用于高速外设(如 SSD、网卡)。

2.3 典型工作流程(以块传输为例)

┌──────┐ 1.配置DMAC ┌────────┐ │ CPU │──────────────>│ DMAC │ └──────┘ └────┬───┘ ^ │ 2.请求总线 │ v │ ┌──────┐ │ 3.总线授予 │ 总线 │ │<──────────────────│ 仲裁 │ │ └──────┘ │ │ │ │ 4.传输数据 │ v │ ┌─────────┐ │ │ 内存/IO │ │ └────┬────┘ │ │ └─────────5.中断─────────┘

流程图解(ASCII)

  1. CPU 设置 DMAC 的源地址、目标地址、字节计数,以及传输模式,然后启动 DMAC。
  2. DMAC 向总线仲裁器发送HOLD信号(总线请求)。
  3. CPU 在适当时候回复HLDA(总线应答),并释放地址总线、数据总线、控制总线的控制权。
  4. DMAC 接管总线,将数据从源地址逐字搬到目标地址。每次传输后 SAR/DAR 自动递增,BCR 递减。
  5. 当 BCR 降为 0,DMAC 发送中断信号给 CPU,报告传输完成。CPU 重新获得总线控制权。

2.4 非内存到内存传输

通常 DMA 用于外设与内存之间(如磁盘→内存),但也可用于内存到内存(例如大块内存拷贝)。不过现代 CPU 的内存拷贝速度更快,所以内存到内存 DMA 不常用。


三、DMA 的工作模式

除了单字节和块传输,还有以下几种常见模式:

模式描述适用场景
轮询/单次一次传输一个数据字,然后重新仲裁低速外设
请求模式外设每次断言 DRQ(数据请求)就传输一个单位需要流控制的外设(如声卡)
级联模式多个 DMA 控制器串联,扩展通道数多个高速外设
自动初始化模式传输完成后自动重装载寄存器的初始值,重复相同传输周期性数据采集
多通道 DMA一个 DMAC 支持多个独立通道,可并行处理多个传输多设备系统(如 PC 芯片组)

四、DMA 与 CPU 的交互细节

4.1 总线仲裁

DMA 设备需要获得总线控制权才能访问内存。仲裁方式通常与总线架构相关:

  • 集中仲裁:一个中心仲裁器(如北桥或芯片组中的 DMA 控制器)决定谁获得总线。
  • 分布式仲裁:每个设备都有总线优先级,通过菊花链或独立请求线竞争。

4.2 缓存一致性

现代 CPU 有多级缓存。当 DMA 将数据写入内存时,缓存中可能存有旧数据(缓存不一致)。解决方案:

  • 非缓存内存:为 DMA 缓冲区设置内存区域为不可缓存(如 Linux 中的dma_alloc_coherent)。
  • 缓存刷新/无效:DMA 传输前,CPU 刷新缓存;传输后,CPU 使无效缓存行。
  • 硬件一致性管理:较新架构(如 x86 的 Intel VT-d、ARM 的 SMMU)支持 I/O 一致性,硬件自动维护缓存一致性。

五、实战案例:磁盘读数据到内存

  1. CPU 初始化 DMA 控制器:
    • 源地址 = 磁盘控制器的数据寄存器端口(I/O 地址)
    • 目标地址 = 内存缓冲区首地址
    • 字节计数 = 4096 字节
    • 控制字:读操作,块传输,传输完成后中断
  2. CPU 启动 DMA,然后执行其他任务。
  3. 磁盘控制器将数据准备好到内部 FIFO,向 DMAC 发送 DMA 请求(DRQ)。
  4. DMAC 获得总线控制权,读取磁盘 FIFO,写入内存,每次传输后地址+1,计数-1。
  5. 传输完 4096 字节后,DMAC 向 CPU 发送中断。
  6. CPU 响应中断,知道数据已可用,继续处理。

六、DMA 的优缺点

优点

  • 降低 CPU 占用率:CPU 从繁重的数据搬运中解放,可以并发执行计算任务。
  • 提高吞吐量:DMA 传输速度通常比 CPU 搬运用时更短(专用硬件流水线)。
  • 支持高速外设:如 NVMe SSD、万兆网卡,没有 DMA 无法达到标称速度。

缺点

  • 硬件成本:需要 DMA 控制器,以及总线仲裁逻辑。
  • 缓存一致性复杂:需要额外处理机制。
  • 总线竞争:大量 DMA 传输可能抢占总线,影响 CPU 访问内存的延迟。

七、现代 DMA 技术演进

7.1 RDMA(Remote Direct Memory Access)

RDMA 允许数据在网络中直接从一个服务器的内存传输到另一台服务器的内存,完全绕过双方 CPU 和操作系统内核。典型实现:InfiniBand、RoCE(RDMA over Converged Ethernet)、iWARP。多用于高性能计算(HPC)和分布式存储。

7.2 IOMMU(I/O Memory Management Unit)

IOMMU 是类似 CPU 的 MMU 的设备,为 I/O 设备提供地址转换能力。主要作用:

  • 设备虚拟化:允许虚拟机直接访问物理设备,IOMMU 将设备的 DMA 地址映射到虚拟机物理地址。
  • 内存保护:限制外设只能访问特定的内存区域,提高安全性。
  • 绕过内核缓冲区:零拷贝网络传输(如 DPDK)利用 IOMMU 将数据直接从网卡传输到用户态内存。

7.3 共享虚拟内存(SVM)

在 GPU 和加速器中,SVM 允许 CPU 与设备共享同一页表,设备可以直接访问 CPU 的虚拟内存地址,无需显式映射物理地址和 DMA 复制。NVIDIA CUDA 的 Unified Memory 就是类似概念。


八、常见问题与答案

Q1:DMA 和中断的关系?
A:DMA 用于数据传输,中断用于告知传输完成。二者协同工作:传输过程中无需中断,结束后触发一次中断即可。

Q2:所有外设都支持 DMA 吗?
A:不是。低速设备(如键盘、鼠标)依靠中断 + PIO(Programmed I/O)就足够。高速块设备(磁盘、网卡)、音视频设备、GPU 等则必须支持 DMA。

Q3:DMA 传输数据时,CPU 能同时访问内存吗?
A:如果总线是共享的,DMA 占用总线时 CPU 无法访问内存(但 CPU 可以执行内部指令或访问缓存)。多总线架构(如分离的 CPU 本地总线和 I/O 总线)可缓解此问题,但通常仍需等待。

Q4:如何编写使用 DMA 的驱动?
A:在 Linux 内核中,使用dma_map_single()映射内存,设置 DMA 描述符,配置硬件寄存器,然后等待中断。用户态可通过ioctlmmap配合零拷贝技术。


九、总结

DMA 技术是高性能 I/O 的基石。它让外设能够绕过 CPU 直通内存,大大释放了 CPU 的算力。从早期的 ISA DMA 控制器到现代的 PCIe BM(Bus Master)设备,再到 RDMA 和 IOMMU,DMA 的演进始终围绕着“更少 CPU 介入、更高带宽、更安全”这一目标。

掌握 DMA 原理,不仅能帮你写出更高效的驱动程序,还能让你在系统性能调优时有的放矢。

思考题:在 Linux 内核中,memcpy是否可能利用 DMA 加速?为什么?
(提示:现代 CPU 的memcpy使用 SIMD 指令或rep movsb,已经很快;DMA 设置开销大,仅适合大块 I/O 场景。)

如果觉得有帮助,欢迎点赞、收藏、转发~


本文首发于 CSDN,未经授权禁止转载。

http://www.jsqmd.com/news/704097/

相关文章:

  • 3步终极优化:用Win11Debloat免费让Windows 11运行速度提升90%
  • 2025届毕业生推荐的十大AI学术方案横评
  • 别再只用OpenCV的imshow了!手把手教你用MFC+GDI+打造像素级精准的工业视觉软件图像显示控件
  • 从LangChain到LangGraph:构建有状态智能体工作流的进阶指南
  • TDC-GP22激光测距精度上不去?可能是你的STM32 HAL库SPI时序没调对
  • marksman:基于本地向量数据库的智能书签管理工具实践
  • MCP 2026租户数据加密不是选配——欧盟DSA/美国SEC新规下,你的租户隔离架构已处于灰色合规区?
  • 避坑指南:HA添加小米设备总提示‘没有设备’?可能是你的小米账号权限不对
  • 终极指南:10分钟搞定kohya_ss AI训练环境,零基础也能玩转Stable Diffusion!
  • 分享2篇最新Harness论文,一篇谷歌,一篇微软
  • 避坑指南:Qt QTableView冻结行列时,你可能遇到的5个诡异Bug及解决方法
  • 元学习:让AI快速掌握新任务的机器学习方法
  • 康复机器人开发笔记:用TwinCAT3和EtherCAT搞定无框力矩电机的第一步
  • 7种高级NLP特征工程技巧提升LLM嵌入效果
  • BERT模型解析:原理、变种与工业应用指南
  • Python 异步文件操作实践
  • gte-base-zh应用解析:在新闻聚合平台中实现内容去重
  • STC15单片机定时器不够用?实战解析蓝桥杯决赛中超声波与NE555的定时器分配策略
  • Snap.Hutao原神工具箱:用开源技术重新定义Windows平台游戏体验
  • Visual C++运行库终极解决方案:一键修复所有Windows软件兼容性问题
  • 从手动F5到全自动智能交付:VS Code Copilot Next 工作流配置进阶路径图(含6阶段能力评估矩阵)
  • Rust 性能优化的五个技巧
  • 2026届毕业生推荐的六大AI辅助写作网站实测分析
  • 如何快速掌握猫抓资源嗅探:技术爱好者的完整实战指南
  • 汽车诊断系统:故障代码读取与维修建议
  • 从ZLToolKit的线程池看C++11/14并发编程:semaphore、thread_group与模板技巧详解
  • 终极窗口调整指南:用WindowResizer强制改变任意窗口尺寸的完整教程
  • 3分钟掌握手机号码精准定位:location-to-phone-number开源工具完全指南
  • BetterNCM Installer:如何用Rust重构网易云插件管理生态?
  • 2026年新生如何集成OpenClaw/Hermes Agent?教程呈现