Skip to content

03. 虚拟内存、多级页表与 TLB 寻址机制 ​

💡 交互图解

本章理论对应的动态微观仿真位于:👉 CS 10 图全屏走查 · FIG 03 虚拟内存穿透与多级页表

1. 为什么需要虚拟内存? ​

早期的批处理系统直接使用物理地址,进程之间不仅没有隔离保护,而且程序大小受限于物理内存容量。 现代操作系统的**虚拟内存(Virtual Memory)**机制赋予了进程三大核心超能力:

  1. 进程隔离与安全保护:每个进程享有独立连续的虚拟地址空间(如 32 位系统 4GB,64 位系统上百 TB),互不干扰;
  2. 物理内存按需分配与共享:同一份动态链接库(如 libc.so)在物理内存中只有一份,通过不同页表映射给所有进程共享;
  3. 突破物理内存限制:利用磁盘 Swap 分区将暂不使用的内存页置换出去,实现远超物理内存容量的程序运行。

2. 虚拟地址转换全链路(Address Translation) ​

以经典 32 位两级分页系统为例(页面大小 4KB):

虚拟地址 (32位):
[  P1 (页目录索引 10位)  |  P2 (页表索引 10位)  |  Offset (页内偏移 12位)  ]

3. 多级页表为什么能节省内存? ​

408 经典真题陷阱: “既然单级页表只需要 4MB 内存,为什么两级页表反而可能需要 4MB 加上 4KB 的目录表,却说多级页表能节省内存?”

  • 单级页表:必须在物理内存中开辟连续的 220×4B=4MB 空间,即使一个进程只占用了 100KB 内存,未使用的页表项也必须全部常驻内存!
  • 多级页表:顶级页目录(Page Directory)只需 4KB。如果一个进程的某个大范围虚拟空间完全未被分配(如代码段和栈段之间的巨大空白区),其对应的顶级 PDE 为空(全 0),底层的二级页表根本不需要创建和分配物理内存!
  • 因此,多级页表实现了页表的稀疏存储与按需构建。64 位体系(x86-64 采用四级页表 PML4 甚至五级页表)更是如此。

4. 缺页中断(Page Fault Exception) ​

当 MMU 遍历页表时,若检查到目标 PTE 的 Present 有效位为 0,说明该页面尚未分配物理内存,或已经被置换到了外存磁盘上。

注意区分中断与异常: 缺页中断在体系结构分类中属于故障(Fault)类异常,发生在指令执行期间。异常处理程序结束后,硬件返回时执行的是触发缺页的那一条原指令(重新尝试访存),而不是下一条指令!


5. 生产级深度关联:零拷贝(Zero-Copy)与 mmap ​

传统磁盘文件发送网络的数据链路需要经过 4 次上下文切换与 4 次数据拷贝:

磁盘→DMA内核PageCache→CPU用户态Buffer→CPUSocket缓冲区→DMA网卡

Linux 零拷贝破解之道:

  1. mmap():直接将文件的物理页缓存通过页表映射到用户进程的虚拟地址空间,用户态无需将文件拷贝一份到堆内存中,节约了一次 CPU 内存拷贝;
  2. sendfile():在内核态直接将 PageCache 的数据指针打入 Socket 缓冲区,结合网卡 Scatter-Gather DMA 特性,实现 0 次 CPU 拷贝! Kafka、Netty、Nginx 能够实现千万级 I/O 吞吐,其底座完全得益于对操作系统虚拟内存与页缓存的深度驾驭。

学思并济 · 躬行求索 | Released under MIT License