4、MMU与IOMMU基础:MMU工作原理、IOMMU工作原理、地址映射与转换

好,咱们进入第四章。这一章讲的是内存管理的基石——MMU和IOMMU。

说实话,很多做应用开发的兄弟可能一辈子都不碰这两个东西。但做固件、做驱动、做系统底层优化,你绕不开它们。我当年刚入行时,第一次调一个DMA传输出错的问题,查了三天,最后发现是IOMMU没配好。嗯,从那以后我就老老实实把这两块啃透了。

4.1 MMU工作原理

MMU,全称Memory Management Unit,内存管理单元。它是个硬件模块,负责把CPU发出的虚拟地址转换成物理地址。

你想想看,如果没有MMU,每个进程直接操作物理内存,那会是什么场景?进程A不小心写了个野指针,直接把进程B的数据给覆盖了。系统崩溃是分分钟的事。

MMU的核心作用有三个:

  • 地址翻译:虚拟地址 → 物理地址
  • 内存保护:检查访问权限,防止越界
  • 页表管理:维护虚拟页到物理页的映射关系

我个人习惯把MMU的工作流程总结成三步:

  1. CPU发出虚拟地址
  2. MMU查页表,找到对应的物理地址
  3. 如果页表命中,直接访问物理内存;如果没命中,触发缺页异常

关键点:MMU的翻译过程是硬件完成的,但页表是操作系统维护的。硬件和软件的分工,就在这里。

4.2 IOMMU工作原理

IOMMU,全称Input/Output Memory Management Unit。说白了,它就是给外设用的MMU。

为什么需要IOMMU?我举个例子。你有一个网卡,它要做DMA传输,直接把数据写到内存里。如果没有IOMMU,网卡看到的地址就是物理地址。这意味着什么?意味着网卡可以访问整个物理内存!这太危险了。

IOMMU的作用:

  • 设备地址翻译:把设备看到的I/O虚拟地址翻译成物理地址
  • 设备隔离:每个设备只能访问它被允许的内存区域
  • 零拷贝支持:通过IOMMU映射,设备可以直接访问用户态缓冲区

我曾经在一个项目中,需要把FPGA采集的数据直接送到用户态应用。如果没有IOMMU,你得先DMA到内核缓冲区,再拷贝到用户态。有了IOMMU,直接映射用户态物理页给FPGA,数据直达,零拷贝。

个人经验:IOMMU的配置比MMU复杂得多。MMU的页表是操作系统自动维护的,IOMMU的页表你得自己配。我建议你在调试IOMMU时,先用简单的1:1映射,跑通了再优化。

4.3 地址映射与转换

地址映射,说白了就是建立一张「翻译表」。这张表叫页表。

页表的结构,不同架构不一样。ARMv8用的是多级页表,x86用的是四级页表。但核心思想是一样的:

  • 虚拟地址被分成多个部分
  • 每一部分作为索引,查一级页表
  • 最后一级页表指向物理页框

举个例子,一个32位系统,页大小4KB:

  • 虚拟地址高20位:页号
  • 虚拟地址低12位:页内偏移
  • 页表把页号映射到物理页框号
  • 物理地址 = 物理页框号 + 页内偏移
// 伪代码:地址翻译过程
uint32_t virtual_to_physical(uint32_t va) {
    uint32_t page_number = va >> 12;      // 高20位
    uint32_t offset = va & 0xFFF;         // 低12位
    uint32_t pfn = page_table[page_number]; // 查页表
    return (pfn << 12) | offset;          // 合成物理地址
}

避坑指南:我曾经在调试一个IOMMU问题时,发现设备DMA总是访问到错误的内存。查了半天,原来是IOMMU页表的粒度没配对。设备用的是2MB大页,我配的是4KB小页。记住:IOMMU的页表粒度必须和设备DMA的传输粒度匹配。

4.4 MMU与IOMMU的对比

特性 MMU IOMMU
服务对象 CPU 外设(DMA设备)
地址类型 虚拟地址 → 物理地址 I/O虚拟地址 → 物理地址
页表维护 操作系统自动管理 驱动手动配置
主要目的 进程隔离、内存保护 设备隔离、零拷贝
性能影响 TLB缓存,影响小 IOTLB缓存,配置不当影响大

嗯,这里要注意。MMU和IOMMU虽然原理相似,但使用场景完全不同。MMU是操作系统层面的,IOMMU是驱动层面的。做零拷贝优化时,IOMMU才是你的主战场。

4.5 核心知识体系

下面这张图,是我自己总结的MMU与IOMMU知识体系。你把它理解透了,后面讲零拷贝实现时,就顺了。

MMU与IOMMU核心知识体系 MMU(内存管理单元) 服务对象:CPU 地址转换:VA → PA 页表维护:操作系统 核心功能: • 进程地址空间隔离 • 内存访问权限控制 • 虚拟内存支持 • 缺页异常处理 关键硬件: • TLB(快表缓存) • 页表基地址寄存器 • 多级页表遍历器 IOMMU(I/O内存管理单元) 服务对象:外设(DMA设备) 地址转换:IOVA → PA 页表维护:驱动手动配置 核心功能: • 设备地址空间隔离 • DMA访问权限控制 • 零拷贝数据传输 • 设备虚拟化支持 关键硬件: • IOTLB(I/O快表缓存) • 设备上下文表 • 中断重映射表 地址映射 原理相通 零拷贝实现的核心:IOMMU映射 + 物理地址连续性管理

这张图把MMU和IOMMU的核心要素都列出来了。你重点关注右侧IOMMU的部分,因为后面讲零拷贝时,IOMMU的映射管理是关键技术。

我的建议:学MMU和IOMMU,不要死记硬背。你找个开发板,写个简单的驱动,配一下IOMMU映射,让设备DMA直接读写用户态内存。跑通了,你就真懂了。

好,这一章就到这里。MMU和IOMMU是地址转换的基石,理解透了,后面讲零拷贝的各种实现方案,你就知道为什么能省掉那些拷贝了。


公众号:蓝海资料掘金营,微信deep3321