linux内核采用页式存储管理。虚拟地址空间划分为固定大小的页面。由MMU在运行时将虚拟地址映射成(或者说转换成)某个物理内存页面中的地址。如图所示:

真实地址虚拟地址映射 nginx_物理地址

与段式存储管理相比,页式存储管理有很多好处。

1.页面都是固定大小的,便于管理;

2.要将一部分物理地址的空间的内容转换到磁盘上的时候,在段式存储管理中要将整个段(通常来说很大)都换出来,而在页式管理中则是按页进行的,效率要高很多。

linux内核设计的段式映射机制把地址0x08049768映射到了其自身后,现在作为线性地址出现了,然后才进入页式映射的过程。每个进程都有其自身的页面目录PGD,指向这个目录的指针保持在每个进程的mm_struct数据结构中。每当调度一个进程进入运行的时候,内核都要为即将运行的进程设置好寄存器CR3,而MMU的硬件则总是从CR3中取得指向当前页面目录的指针,但cpu在执行程序的时候使用的是虚拟地址,而MMU硬件在进行映射时所用的则是物理地址。//这些都是在inline函数switch_mm()中完成的。

在页面映射的过程中,cpu要访问内存三次,第一次是页面目录,第二次是页面表,第三次才是访问真正的目标,所以虚逆内存的高效实现有赖于高速缓存(cache)的实现。

第一次地址映射会失败,=》缺页异常,MMU重启映射,缺页异常处理,完成后再次进行物理内存的分配,进行二次映射。



 缺页异常:CPU通过地址总线可以访问连接在地址总线上的所有外设,包括物理内存、IO设备等等,但从CPU发出的访问地址并非是这些外设在地址总线上的物理地址,而是一个虚拟地址,由MMU将虚拟地址转换成物理地址再从地址总线上发出,MMU上的这种虚拟地址和物理地址的转换关系是需要创建的,并且MMU还可以设置这个物理页是否可以进行写操作,当没有创建一个虚拟地址到物理地址的映射,或者创建了这样的映射,但那个物理页不可写的时候,MMU将会通知CPU产生了一个缺页异常。


推荐给大家一本书:《linux内核源代码情景分析》第二章有详细的虚拟地址映射的过程;