1.2 Linux内存架构
  为了执行一个进程,Linux内核为请求的进程分配一部分内存区域。该进程使用该内存区域作为其工作区并执行请求的工作。它与你的申请一个办公桌,然后使用办公桌来摆放纸张、文档和备忘录来执行你的工作类似。不同之处是内核必须使用更动态的方式来分配内存空间。有时运行的进程数会达到数万个,但内存的数量是有限的。因此,Linux内核必须有效地处理内存。在本节,我们将会讲述Linux的内存结构、地址分布和Linux如何有效地管理内存空间。
  1.2.1 物理和虚拟内存
  我们已经要面对选择32位和64位系统的问题。对于企业级客户的其中一个重要的不同是虚拟内存的地址是否能超过4GB。从性能的角度来看,理解32位和64位系统中Linux内核如何把物理内存映射到虚拟内核是重要的。
  从图1-10中,可以看出Linux内核在处理32位和64位系统内存的方式上的明显的差别。介绍内存内存到虚拟内存的映射细节已经超出了本文的范围,所以本文着重介绍Linux内存结构的部分细节。
  在32位的架构上,如IA-32,Linux内核只能直接访问物理内存的前1GB(当考虑部分保留是为896MB)。所谓的 ZONE_NORMAL之上的内存必须要被映射到1GB以上的内存中。该映射对于应用来说是完全透明的,但是在ZONE_HIGHMEM中申请内存页会导致一个性能的稍微下降。
  另一方面,在64位的架构上,如x86-64(也叫x64),ZONE_HIGHMEM可以一直延伸到64GB,或者在IA-64系统上可以延伸到128GB。正如你所见到的,通过64位的架构,内存页从ZONE_HIGHMEM到ZONE_NORMAL的映射开销可以被消除。


  图1-10 32位和64位系统的Linux内核内存布局

  虚拟内存地址布局
  图1-11展示了32位和64位架构的Linux虚拟地址布局。
  在32位架构上,一个进程能访问的大的地址空间为4GB。这是32位虚拟地址的一个限制。在标准的实现里,虚拟地址空间被分为3GB的用户空间和1GB的内核空间。这有一点类似于4G/4G寻址布局实现的变种。
  另一方面,在64位架构中,如x86-64和IA64,没有此限制。每个单独进程都能得益于于广阔而巨大的地址空间。


  图1-11 32位和64位架构的虚拟内存地址布局

  1.2.2 虚拟内存管理
  操作系统的物理内存架构对于应用和用户来说通常是不可见的,因为操作系统会把任何的物理内存都映射到虚拟内存中。如果我们想要理解在Linux操作系统中的调优的可能性,我们必须理解Linux如何处理虚拟内存。正如1.2.1中“物理内存和虚拟内存”的介绍,应用并不能申请物理内存,但当向Linux内核请求一定大小的内存映射,得到的是一个虚拟内存的映射。如图1-12所示,虚拟内存不一定要映射到物理内存中。如果你的应用申请了大量的内存,这些内存中的一部分可能映射到磁盘的swap文件中。
  图1-12展示了,应用程序通常直接写不直接写磁盘,而是直接写缓存(cache)或缓冲(buffer)。当pdflush内核线程空闲或者文件大小超出了缓存缓冲大小时,pdfflush内核线程会将缓存/缓冲的数据清空并写入到磁盘中。参阅“清空脏缓冲”。


  图1-12 Linux虚拟内存管理

  Linux内核处理物理磁盘的写操作与Linux管理磁盘缓存紧密相连。其他的操作系统只分配部分内存作为磁盘缓存,而Linux处理内存资源则更加有效。默认的虚拟内存管理配置分配所有可用的空闲内存作为磁盘的缓存。因此在拥有大量内存的Linux系统中,经常看到只有20MB的空闲内存。
  在相同的情况下,Linux管理swap空间也非常有效率。swap空间被使用时并不意味着出现内存的瓶颈,它恰恰证明了Linux管理系统资源如何的有效。详见“页帧回收”。