VMA就像是一个在你的程序和内核之间的契约。你要求一些事情被处理(内存分配、文件映射等等),内核说:“可以”,并且创建或者更新合适的VMA。但是他实际上并不履行请求权,他会等待指到一个缺页中断发生后才去做实际的工作。内核很懒,就是一个骗人的败类;这是虚拟内存的基本原则。这应用到大多数情形下,一些熟悉的一些令人吃惊的,但是规则是VMA记录达成了什么协议,而PTE反映内核实际做了什么。这两个数据结构一起管理一个程序的内存;包括解决缺页中断、释放内存、换出内存等等。让我们举一个内存分配的简单例子:
当程序通过brk()系统调用申请更多的内存空间时,内核简单地更新堆的VMA。在这一点上,没有页框做实际的分配并且新分配的页面在内存中不是处于当前的。一旦程序进入这些页面,处理器缺页中断发生并且do_page_fault()被调用。他使用find_vma()函数搜索覆盖缺页中断虚拟地址空间的VMA。如果找到,VMA上的权限(读或者写)也会再次被检查。如果没有找到合适的VMA,没有契约覆盖试图进入的内存区,处理器产生段错误。
当找到一个VMA,内核必须查看PTE内容和VMA的类型来处理这个缺页中断,在我们的例子中,PTE显示的页面不是当前的。实际上,我们的PTE是完全空白的(全是0),在linux中意味着虚拟页面没有被映射。一旦这是一个匿名VMA,我们必须由do_anonymous_page()来处理一个纯RAM事务,他分配一个页面帧,用它来映射发生缺页异常的虚拟页面。
事情可能会有些不同。对一个换出页的PTE,例如,Present标志位为0但是整个不是0。他存储持有页面内容的交换位置,这个位置必须用do_swap_page()函数从磁盘上读取加载到一个页面,该函数被一个异常调用。
这里总结了内核的用户内存管理器开始一半,在接下来的文章中,我们把文件加入进来,建立一个完整的内存基础构架图,包括他们实现的性能。