虚拟内存(Virtual Memory) 是指计算机呈现出要比实际拥有的内存大得多的内存量。因此它允许程序员编制并运行比实际系统拥有的内存大得多的程序。这使得许多大型项目也能够在具有有限 内存资源的系统上实现。一个很恰当的比喻是:你不需要很长的轨道就可以让一列火车从上海开到北京。你只需要足够长的铁轨(比如说3公里)就可以完成这个任务。采取的方法是把后面的铁轨立刻铺到火车的前面,只要你的操作足够快并能满足要求,列车就能象在一条完整的轨道上运行。这也就是虚拟内存管理需要完成的 任务。在Linux 0.11内核中,给每个程序(进程)都划分了总容量为64MB的虚拟内存空间。因此程序的逻辑地址范围是0x0000000到0x4000000。

linux系统对于内存的管理有分段和分页方式,对于每个页的使用情况之用struct page数组mem_map进行维护。在linux系统中存在用户空间和内核空间,这两个空间是针对于线性地址的。其中内核空间的线性地址一般为3G~4G,而用户空间的地址为0~3G。

当程序运行在用户态的时候,只能访问0~3G的用户空间,而运行在内核态的时候可以访问3~4G的内核空间。假如内核空间的线性地址与物理地址是一对一映射的时候,很显然内核只能访问1G的内存空间。这种设计是不允许的,因为内核应该可以访问整个内存空间。因此linux的设计者提出了另一个概念即高端内存和低端内存。低端内存是从3G开始的896M的线性地址空间,这部分线性地址直接映射到物理地址的0~896M。而之后的部分线性地址为动态的映射,映射到物理内存896M之后的部分。

为了将线性地址映射到物理地址,需要页目录表和页表。在linux2.4中每个进程都有属于自己的页目录表和页表。当创建新的进程并创建新的页表的时候,会把进程的0~768项清空(每个页目录对应4M内存,768项正好是0~3G),然后把内核进程的768~1024项拷贝到当前进程,这样就实现了所有进程共享内核地址空间。但是这并不意味着所有进程都能访问内核地址空间,因为只有发生中断或者产生系统调用等需要进入内核态运行的时候才会产生3~4G的线性地址。