逻辑地址(虚拟地址)和物理地址是如何转换的?(MMU)
逻辑地址(虚拟地址)到物理地址的转换是现代计算机操作系统内存管理的核心机制。这个过程主要由硬件组件 MMU(Memory Management Unit,内存管理单元) 负责,并由操作系统(OS)通过页表进行配合。
目前最主流的内存管理方式是 分页机制(Paging)。下面我将以分页机制为例,详细解释转换过程。
1. 核心概念
在理解转换之前,需要明白三个关键概念:
- 逻辑地址(虚拟地址):CPU 产生的地址,程序代码中使用的地址。
- 物理地址:内存条(RAM)上实际的存储单元地址。
- 页(Page)与页框(Page Frame):
- 虚拟内存被切分成固定大小的块,叫“页”(通常是 4KB)。
- 物理内存被切分成同样大小的块,叫“页框”或“物理页”。
- 转换的本质就是:找到“虚拟页”对应的是哪个“物理页框”。
2. 地址的结构
一个虚拟地址在二进制层面被分为两部分:
- 虚拟页号 (VPN):相当于书的“页码”。MMU 用它来查找物理页。
- 页内偏移量 (Offset):相当于“第几行第几个字”。这个值在转换过程中保持不变,直接拷贝到物理地址中。
3. 转换过程(MMU 的工作流)
当 CPU 执行一条指令需要访问内存地址(例如 MOV EAX, [0x12345])时,发生了以下步骤:
第一步:TLB 查找(快表)
MMU 内部有一个高速缓存,叫做 TLB(Translation Lookaside Buffer,转译后备缓冲器/快表)。它存储了最近用过的“虚拟页号 物理页框号”的映射关系。
- 命中 (Hit):如果 TLB 里有这个虚拟页号,直接取出物理页框号,拼接偏移量,生成物理地址。速度极快。
- 未命中 (Miss):如果 TLB 里没有,MMU 就需要去访问内存中的“页表”。
第二步:查询页表(Page Table Walk)
页表是存储在主存(RAM)中的一张映射表,由操作系统维护。
- MMU 根据 CR3 寄存器(在 x86 架构中)找到页表的起始物理地址。
- MMU 用虚拟页号作为索引,在页表中找到对应的页表项(PTE, Page Table Entry)。
第三步:检查页表项(PTE)状态
找到页表项后,MMU 会检查里面的标志位:
- 有效位 (Valid Bit):
- 如果是 1:表示该页在物理内存中。MMU 提取出物理页框号 (PFN)。
- 如果是 0:表示该页不在物理内存中(可能在硬盘的 Swap 分区里,或者还未分配)。此时 MMU 会触发一个 缺页异常 (Page Fault),将控制权交给操作系统。操作系统负责把数据从硬盘加载到内存,更新页表,然后 CPU 重新执行这条指令。
- 权限位 (R/W, User/Supervisor):
- MMU 会检查当前操作是否合法(例如:尝试写入只读页面,或用户态程序尝试访问内核空间)。如果不合法,MMU 触发 段错误 (Segmentation Fault)。
第四步:合成物理地址
如果一切正常,MMU 将从页表中拿到的 物理页框号 (PFN) 与原地址中的 页内偏移量 (Offset) 拼接。
第五步:访问物理内存
CPU 使用这个最终生成的物理地址去访问缓存(L1/L2/L3 Cache)或主存(RAM)获取数据。
4. 进阶:多级页表(Multi-Level Paging)
在 32 位或 64 位系统中,如果只用一张大表来存所有映射,页表会占用巨大的连续内存空间(例如 32 位系统每进程需要 4MB 连续内存存页表,64 位则大得离谱)。
因此,现代 CPU 使用 多级页表(类似书的“章-节-小节”目录结构):
- 虚拟地址被拆分成:
一级页号 | 二级页号 | ... | 偏移量。 - CR3 寄存器 指向一级页目录。
- 一级页号 找到二级页表的地址。
- 二级页号 找到物理页框号。
- 这种方式允许页表分散存储,且对于未使用的内存空间,不需要创建对应的下级页表,极大地节省了内存。
5. 总结图解
假设虚拟地址是 0x1234 (二进制简化版),系统页大小为 0x100 (最后两位是偏移)。
- 拆分:
- 虚拟地址
0x1234VPN:0x12, Offset:0x34
- 虚拟地址
- MMU 查表:
- 查找 VPN
0x12对应的物理帧号 (PFN)。 - 假设页表中记录:
0x120x56。
- 查找 VPN
- 拼接:
- PFN
0x56+ Offset0x34物理地址0x5634。
- PFN
一句话总结:
MMU 通过 TLB(快速缓存)和 多级页表(内存查找),将虚拟地址的 页号 替换为物理内存的 页框号,并保留 偏移量 不变,从而得到最终的物理地址。