C++面试宝典:linux内存管理单元(mmu)

1、为什么使用多级页表来完成映射

用来将虚拟地址映射到物理地址的数据结构称为页表,实现两个地址空间的关联最容易的方式是使用数组,对虚拟地址空间中的每一页, 都分配一个数组项。该数组指向与之关联的页帧,但这会引发一个问题,例如,IA-32体系结构使用4KB大小的页,在虚拟地址空间为4GB的前提下,则需要包含100万项的页表.
4*1024*1024/4=1000000
而每个进程都需要自身的页表,这回导致系统中大量的所有内存都用来保存页表。这个问题在64位体系结构下,情况会更加糟糕。

Page Table Entry
设想一个典型的32位的X86系统,它的虚拟内存用户空间(user space)大小为3G, 并且典型的一个页表项(page table entry, pte)大小为4 bytes,每一个页(page)大小为4k bytes。那么这3G空间一共有(3G/4k=)786432个页面,每个页面需要一个pte来保存映射信息,这样一共需要786432个pte!

如何存储这些信息呢?一个直观的做法是用数组来存储,这样每个页能存储(4k/4=)1K个,这样一共需要(786432/1k=)768个连续的物理页面(phsical page)。而且,这只是一个进程,如果要存放所有N个进程,这个数目还要乘上N! 这是个巨大的数目,哪怕内存能提供这样数量的空间,要找到连续768个连续的物理页面在系统运行一段时间后碎片化的情况下,也是不现实的。
C++面试宝典:linux内存管理单元(mmu)

多级页表从两个方面减少了存储器要求。

  1. 第一,如果一级页表中的第一个PTE(分页)是空的,那么相应的二级页表就根本不会存在,这代表着一种巨大的潜在节约,因为对于一个典型的程序,比如4GB,8GB的虚拟地址空间的大部分都将是未匹配的。
  2. 第二,只有一级页表才需要总是在主存中;虚拟存储器系统可以在需要时创建,页面掉入或调出二级页表,这就减少了主存的压力;只有最经常使用的二级页表才需要缓存在主存中,这种离散的存储方式是非常便利的