总结:MMU -- 包括 TLB 以及 Table Walk Unit ,以及内存 Page Table

1. MMU 结构以及工作过程

大多数使用MMU的机器采用内存分页机制,虚拟地址空间以页(Page)为单位,相应的,物理地址空间也被划分为页帧(Frame)页帧必须与保持相同的大小,通常为4KB,对于大页,页帧可以是2MB1GB。大页一般用于服务器,用于系统分配大量数据,减少缺页中断的发生。

MMU通过页表(Page Table)将虚拟地址映射到物理地址,页表存储在主存中,由系统内核创建及管理。

CPU with MMU

MMU由两部分组成:TLB(Translate Look-aside Buffer),以及Table Walk Unit

  1. TLB (Translation Lookaside Buffer):缓存最近使用的 VAPA 的映射;
  2. Table Walk Unit:如果TLB没有命中CPU发出的VA,则由Table Walk Unit根据位于物理内存中的页表(Page Table)完成VAPA的查找。

CPU访问内存的时候,将VA发给MMUMMU先在TLB中查找是否有对应的PA,如果有,则直接返回对应的PA;如果没有,则由Table Walk Unit根据位于物理内存中的页表完成查找。

在上述过程中,如果Table Walk Unit没有找到对应的PA,则向CPU发出Page fault中断,CPU处理缺页中断(具体见后面章节描述)。

MMU的工作过程图示:

MMU Work Process

CPU发出的VA由两部分组成:VPN(Virtual Page Number) + offset。对应的,转换之后的物理地址也有两部分:页框号PFN(Physical Frame Number) + offset

VPN to PFN

1.1 从VAPA,MMU处理流程图

MMU VA to PA Process

2. 页表结构

现代CPU一般采用四级页表结构。以32位地址空间的二级页表为例,CPU发出的虚拟地址被拆分分为:页目录(Page Directory)、页表(Page Table)、页内偏移(Page Offset)三级(以4k为例,即12位)。

VPN的最高10位用于索引页目录,紧接的10位用于索引页表索引,最低12位为页内偏移地址。拆分结构如下图所示:

Page Table Structure

2.1 MMU查找过程

MMU先根据一级页表的物理地址和一级页表Index去一级页表中找PTE,PTE中的地址不再是最终的物理地址,而是二级页表的物理地址。

根据二级页表物理地址和二级页表index去二级页表中找PTE,此时PTE中的地址才是真实的物理地址。

根据此物理地址和offset找到最终的物理内存地址。

MMU Lookup Process

使用二级页表的好处是如果一级页表中的某一个PTE没有命中,那这一PTE对应的整个二级页表就不存在。

2.2 进程页表与 Address Space ID

操作系统会为每个进程分配一个页表,该页表使用物理地址存储。当进程使用类似malloc等需要映射代码或数据的操作时,操作系统会在随后马上修改页表以加入新的 物理内存

每次切换进程都需要进行TLB清理。这样会导致切换的效率变低。为了解决问题,TLB引入了ASID(Address Space ID)ASID的范围是0-255ASID由操作系统分配,当前进程的ASID值被写在ASID寄存器(使用CP15 c3访问)TLB在更新页表项时也会将ASID写入TLB

MMU在查找TLB时, 只会查找TLB中具有相同ASID值TLB行。且在切换进程时,TLB中被设置了ASIDTLB行不会被清理掉,当下次切换回来的时候还在。所以ASID的出现使得切换进程时不需要清理TLB中的所有数据,可以大大减少切换开销

3. 页表项(PTE)TLB 中的标志位

在进程的虚拟内存空间中,每一个虚拟内存页在页表中都有一个PTE与之对应,在32位系统中,每个PTE占用4个字节大小,其中保存了虚拟内存页背后映射的物理内存页的起始地址,以及进程访问物理内存的一些权限标识位。

PTE in Page Table

由于内核将整个物理内存划分为一页一页的单位,每个物理内存页大小为 4K,所以物理内存页的起始地址都是按照 4K 对齐的,也就导致物理内存页的起始地址的后 12 位全部是 0,我们只需要在PTE中存储物理内存地址的高 20 位就可以了,剩下的低 12 位可以用来标记一些权限位。

PTE flags

一些标志位的含义如下:

  • P(0):映射的物理内存是否在内存中。值为0表示可能被换出,需要从磁盘中读取。此时,其他bit位存放的是物理内存页在磁盘中的位置;
  • R/W(1):值为0表示该物理页只读,针对该页面的写操作触发page fault异常。比如,使用fork创建子进程之后,父子进程内存空间完全一样,页表中的内容也是一样的,父子进程中的PTE均指向同一物理内存。此时,内核将父子进程中的PTE均修改为只读的,并将父子进程共同映射的这个物理内存引用计数+1。当子进程需要进行写操作时,在内核的page fault异常处理时,发现这个物理页面的引用计数大于1,说明是多进程共享同一个物理内存,将进行写时拷贝(Copy On Write, COW),内核为子进程重新分配一个物理页,复制原有物理页中的内容到新物理页,减少物理页面的引用计数,并修改子进程PTE中的R/W标志位。
  • PCD(2)Page Cache Disable,表示PTE指向的物理内存页面中的内容,是否可以被缓存到Cache中。在SOC异构处理器共享同一块物理内存时,可以使用PCD创建禁止CachePTE
  • PWT(3): Page Write-Through,表示PTE指向的CPU Cache中的内容,是直接写入物理内存(Write-Through),还是在Cache-line被中的内容被替换时写入物理内存(Write-Back)。

4. 缺页处理过程

当调用malloc时,内核不会立即分配物理内存,仅在进程的虚拟地址空间中创建VMA(vm_area_struct),记录该段虚拟地址的范围和权限。此时PTE尚未建立或P位为0。当进程首次访问该虚拟地址时,MMU触发Page Fault异常,CPU陷入内核态。

内核根据异常地址查找进程的VMA,按以下三种情况处理:

情况一:非法地址 —— 地址不属于任何VMA,内核向进程发送SIGSEGVSegmentation Fault),进程被终止。

情况二:首次访问(页面尚未分配物理内存) —— PTE为空,内核分配物理页框、清零、建立PTE映射(读操作可先映射到共享零页,写时再分配,即COW)。

情况三:页面被换出到 Swap —— PTEP位为0,其余位记录了Swap位置。内核分配新物理页框,从Swap读回数据,更新PTE并置P位为1。

4.1 物理内存分配完成之后

PTE映射建立后,内核刷新TLB使旧缓存失效,然后返回用户态重新执行触发异常的指令。MMU此次通过Table Walk Unit查到有效PTE,完成VA → PA转换并缓存到TLB,CPU正常访问物理内存。

mmu_page_fault_process

参考




    Enjoy Reading This Article?

    Here are some more articles you might like to read next:

  • NVIDIA GPU 架构:SP、SM 与 LSU 工作原理详解
  • al-folio 模板定制修改总结
  • al-folio 本地部署记录(Ubuntu 24.04)
  • C++ Traits
  • 道格拉斯-普克算法(Douglas–Peucker algorithm)