4、MMU与IOMMU基础:MMU工作原理、IOMMU工作原理、地址映射与转换
好,咱们进入第四章。这一章讲的是内存管理的基石——MMU和IOMMU。
说实话,很多做应用开发的兄弟可能一辈子都不碰这两个东西。但做固件、做驱动、做系统底层优化,你绕不开它们。我当年刚入行时,第一次调一个DMA传输出错的问题,查了三天,最后发现是IOMMU没配好。嗯,从那以后我就老老实实把这两块啃透了。
4.1 MMU工作原理
MMU,全称Memory Management Unit,内存管理单元。它是个硬件模块,负责把CPU发出的虚拟地址转换成物理地址。
你想想看,如果没有MMU,每个进程直接操作物理内存,那会是什么场景?进程A不小心写了个野指针,直接把进程B的数据给覆盖了。系统崩溃是分分钟的事。
MMU的核心作用有三个:
- 地址翻译:虚拟地址 → 物理地址
- 内存保护:检查访问权限,防止越界
- 页表管理:维护虚拟页到物理页的映射关系
我个人习惯把MMU的工作流程总结成三步:
- CPU发出虚拟地址
- MMU查页表,找到对应的物理地址
- 如果页表命中,直接访问物理内存;如果没命中,触发缺页异常
关键点: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的核心要素都列出来了。你重点关注右侧IOMMU的部分,因为后面讲零拷贝时,IOMMU的映射管理是关键技术。
我的建议:学MMU和IOMMU,不要死记硬背。你找个开发板,写个简单的驱动,配一下IOMMU映射,让设备DMA直接读写用户态内存。跑通了,你就真懂了。
好,这一章就到这里。MMU和IOMMU是地址转换的基石,理解透了,后面讲零拷贝的各种实现方案,你就知道为什么能省掉那些拷贝了。
公众号:蓝海资料掘金营,微信deep3321