![](http://net.pku.edu.cn/%7Eyhf/lyceum/linuxK/mm/vm.gif)
![](http://net.pku.edu.cn/%7Eyhf/lyceum/linuxK/mm/page-tables.gif)
二. 页面分配与回收
所有的物理页面用包含mem_map_t结构的链表mem_map来描叙,这些结构在系统启动时初始化。每个 mem_map_t描叙了一个物理页面。
使用free_area数组管理空闲块,实现页面的分配与回收
![](http://net.pku.edu.cn/%7Eyhf/lyceum/linuxK/mm/free-area.gif)
三. 内存映射
将映象连接到进程虚拟地址空间的过程称为内存映射。
映象执行时,可执行映象的内容将被调入进程虚拟地址空间中。可执行映象使用的共享库同样如此。然而可执行文件实际上并没有调入物理内存,而是仅仅连接到进 程的虚拟内存。当程序的其他部分运行时引用到这部分时才把它们从磁盘上调入内存。
![](http://net.pku.edu.cn/%7Eyhf/lyceum/linuxK/mm/vm_area.gif)
可执行映象映射到进程虚拟地址时将产生一组相应的vm_area_struct数据结构。每个vm_area_struct数据结构表示可执行映象的一部 分:可执行代码、初始化数据(变量)、未初始化数据等等。Linux支持许多标准的虚拟内存操作函数,创建vm_area_struct数据结构时有一组 相应的虚拟内存操作函数与之对应。
每个进程的虚拟内存用一个mm_struct来表示。它包含当前执行的映象(如BASH)以及指向vm_area_struct 的大量指针。每个vm_area_struct数据结构描叙了虚拟内存的起始与结束位置,进程对此内存区域的存取权限以及一组内存操作函数。这些函数都是 Linux在操纵虚拟内存区域时必须用到的子程序。其中一个负责处理进程试图访问不在当前物理内存中的虚拟内存(通过页面失效)的情况。此函数叫 nopage。它用在Linux试图将可执行映象的页面调入内存时。
四. 请求换页
当可执行映象到进程虚拟地址空间的映射完成后,它就可以开始运行了。由于只有很少部分的映象调入内存,所以很快就会发生对不在物理内存中的虚拟内存区域的访问。当进程访问无有效页表入口的虚拟地址时,处理器将向Linux报告一个页面错误。
页面错误带有失效发生的虚拟地址及引发失效的访存方式。Linux必须找到表示此区域的vm_area_struct结构。对 vm_area_struct数据结构的搜寻速度决定了处理页面错误的效率,而所有vm_area_struct结构是通过一种AVL(Adelson- Velskii and Landis) 树结构连在一起的。如果无法找到vm_area_struct与此失效虚拟地址的对应关系,则系统认为此进程访问了非法虚拟地址。这时Linux将向进程 发送SIGSEGV信号,如果进程没有此信号的处理过程则终止运行。
如果找到此对应关系,Linux接下来检查引起该页面错误的访存类型。如果进程以非法方式访问内存,比如对不可写区域进行写操作,系统将产生内存错误的信号。
首先Linux必须区分位于交换文件中的页面和那些位于磁盘上的可执行映象。
不是所有的vm_area_struct数据结构都有一组虚拟内存操作函数,它们有的甚至没有nopage函数。这是因为 Linux通过分配新的物理页面并为其创建有效的页表入口来修正这次访问。如果这个内存区域存在nopage操作函数,Linux将调用它。
一般Linux nopage函数被用来处理内存映射可执行映象,同时它使用页面cache将请求的页面调入物理内存中去。
当请求的页面调入物理内存时,处理器页表也必须更新。更新这些入口必须进行相关硬件操作,特别是处理器使用TLB时。这样当页面失效被处理完毕后,进程将从发生失效虚拟内存访问的位置重新开始运行。
六. 换出与丢弃页面
八. swap cache
九. 页面的换入
参考文献:
http://net.pku.edu.cn/~yhf/lyceum/linuxK/