Files
2026-03-22 17:40:44 +08:00

5.0 KiB
Raw Permalink Blame History

这三个问题正好卡在“虚拟内存—总线—中断控制器”的交界处,我直接给你一个工程级、可运行在脑子里的模型。


一、DMA 用的是虚拟地址还是物理地址?

短答DMA 面向的是“物理侧地址”,不是普通的 CPU 虚拟地址。 但在现代系统里会多一层:I/O 虚拟地址IOVA


1最基础模型无 IOMMU

CPU  虚拟地址(VA) ──页表──> 物理地址(PA)
DMA                         直接使用 PA

流程:

  1. 驱动在内核里分配一块内存(这时它有 VA 和对应的 PA
  2. 驱动把物理地址 PA写给设备DMA 描述符里)
  3. 设备按这个 PA 直接读/写内存

👉 结论:

DMA 不认识进程的虚拟地址VA只认物理地址PA

2现代模型有 IOMMU

引入一个关键组件IOMMU

CPU   VA ──> PA
DMA  IOVA ──IOMMU──> PA

此时流程变成:

  1. 驱动向 IOMMU 注册一段内存映射
  2. 得到一个 IOVA给设备用的“虚拟地址”
  3. 设备用 IOVA 发起 DMA
  4. IOMMU 翻译成真实物理地址 PA

👉 关键好处:

✔ 安全:设备不能乱访问内存
✔ 灵活:可以映射不连续的物理页
✔ 虚拟化支持多VM

3一句话总结

无 IOMMUDMA 用物理地址
有 IOMMUDMA 用 IOVA再映射到物理地址

二、DMA 会不会和 CPU 冲突?能不能同时工作?

短答:可以完全并行,但会“竞争资源”,不是互斥。


1并行性关键认知

CPU执行指令
DMA走总线搬数据

👉 两者是独立硬件单元

✔ 可以同时工作
✔ 不需要互相等待

2那会不会冲突——会但在“带宽层面”

冲突发生在这里:

内存控制器 / 总线(如 PCIe

多个参与者:

CPUload/store
DMA设备
GPU显存访问

都要访问内存:

→ 需要仲裁arbitration

3真实情况

CPU读写内存  ←→  DMA读写内存
        ↓
   内存控制器调度

结果:

✔ 可以并行
✔ 但会抢带宽(变慢)
❌ 不是“谁工作另一个就停”

4一个直觉类比

内存 = 公路
CPU = 小汽车
DMA = 卡车

✔ 可以同时跑
✔ 但车多会堵

三、DMA 如何让 CPU 产生中断?

这个是很多人最模糊的一点,我们拆到“硬件信号级”。


1关键DMA 本身“不发中断”

👉 非常重要:

DMA ≠ 中断源
设备(或控制器)才是

2完整路径标准 PC 架构)

设备/NIC/USB控制器
        ↓
发中断信号MSI / MSI-X / 旧IRQ
        ↓
中断控制器APIC
        ↓
CPU

3现代方式MSIMessage Signaled Interrupt

不用传统“中断线”,而是:

设备发一个“特殊的内存写”

具体:

设备(通过 PCIe
    写入某个固定地址APIC寄存器
这次“内存写” = 中断信号

4流程串起来DMA + 中断)

1设备 DMA 写数据到内存 buffer

2设备决定
    - 立刻中断?
    - 延迟coalescing

3如果要中断
    设备发 MSI本质是一次内存写

4APIC 接收到
    → 通知 CPU

5CPU
    - 保存上下文
    - 跳转中断处理函数

5为什么设计成“内存写触发中断”

好处:

✔ 不需要专用中断线(可扩展)
✔ 支持多核可以指定哪个CPU
✔ 和DMA同一套总线PCIe

四、把三件事彻底统一(你要形成这个模型)


1地址体系

CPUVA → PA
DMAIOVA → PA或直接 PA

2执行关系

CPU 执行程序
DMA 搬数据
→ 完全并行

3通知机制

DMA完成只是数据好了
        ↓
设备决定是否发中断
        ↓
MSI → APIC → CPU

五、一个完整“工业级时间线”(你可以脑内跑)

t0驱动配置 DMA bufferIOVA/PA

t1设备收到数据
t2DMA → 写入内存

t3CPU 正在跑别的程序(完全并行)

t4设备决定
    “现在通知CPU”

t5发 MSI一次PCIe内存写

t6APIC → CPU
    CPU 被打断

t7中断处理函数
    从 buffer 读数据

六、最后给你三句“压缩理解”

1DMA 只负责“搬数据”,不负责“通知”
2地址上DMA 不用 CPU 的虚拟地址(除非经 IOMMU 转换)
3CPU 和 DMA 并行运行,只在“内存带宽”上竞争

如果你想再往下走一步,下一层是非常关键的:

  • cache coherenceDMA 写内存CPU cache 怎么一致?)
  • zero-copy 为什么难(缓存 + 映射问题)
  • DPDK 为什么要关 cache / 绑核

这些是“性能优化”的真正核心。