本文为IBM RedBook的Linux Performanceand Tuning Guidelines的1.2节的翻译
原文地址:http://www.redbooks.ibm.com/redpapers/pdfs/redp4285.pdf
原文作者:Eduardo Ciliendo, Takechika Kunimasa, Byron Braswell
译文例如以下:
1.2 Linux内存架构
为了运行一个进程,Linux内核为请求的进程分配一部分内存区域。该进程使用该内存区域作为其工作区并运行请求的工作。它与你的申请一个办公桌。然后使用办公桌来摆放纸张、文档和备忘录来运行你的工作相似。
不同之处是内核必须使用更动态的方式来分配内存空间。有时运行的进程数会达到数万个,但内存的数量是有限的。
因此。Linux内核必须有效地处理内存。在本节,我们将会讲述Linux的内存结构、地址分布和Linux怎样有效地管理内存空间。
今天我们已经要面对选择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管理系统资源怎样的有效。详见“页帧回收”。
页帧的分配
一页是一组连续线性的物理内存(页帧)或虚拟内存。Linux内核以页为单位管理内存。
一页的大小通常为4K字节。当一个进程申请一定数量的页时。假设可用的页足够。Linux内核立即分配给进程。否则。内存页必须从其它一些进程或内存页缓存中获取。
Linux内存知道可用的内存页的数量及位置。
伙伴系统
Linux内核通过一种被称作伙伴系统的机制管理空暇页。伙伴系统管理空暇页并尽力为分配请求分配页。它尽最大努力保持内存区域的连续。
假设不考虑分散的小页。将会导致内存碎片。并导致在连续区域内申请一大段的页变得困难。它将导致效率低下的内存使用和性能下降。
图1-13说明了伙伴系统怎样分配页。
图1-13 伙伴系统
当尝试分配页失败,页回收会被激活。參阅“页帧回收”。
你能够通过/proc/buddyinfo查找伙伴系统的信息。详见“Memory used in a zone”。
页帧回收
当一个进程请求一定数量的页的映射时,假设页不可用,Linux内核新的请求尝试通过释放某些页(先前使用过但如今不再使用,但基于某些原则仍然被标记为活动状态的页)并分配内存给该进程。这个过程被称为面帧回收。
kswapd内核线程和try_to_free_page()内核函数被用来负责页的回收。
kswapd线程通常处于可中断的睡眠状态,当某一区域中的自由页低于一个阈值时,kswapd线程会被伙伴系统调用。它尝试基于近期最少使用算法从活动页中找出候选页。近期最少使用的页将会被首先释放。活动列表和非活动列表被用于维护候选页。
kswapd扫描部分活动列表并检查页的使用情况。把近期没有使用的页放到非活动列表中。你能够使用vmstat -a命令查看哪些内存是活动的和哪些内存是非活动的。
kswapd也遵循其它原则。页的使用主要是为了两个用途:页缓存和进程地址空间。页缓存是页映射到一个磁盘文件。
属于一个进程地址空间的页(被称为匿名内存,由于它没有映射到不论什么文件,也没有名字)被用于堆和栈。參阅1.1.8。“进程内存段”。
当kswapd回收页时。它将会尽量压缩页缓存而不是把进程的页page out(或者swap out)。
Page out和swap out:“page out”和“swap out”非常多时候都会被混淆。“page out”是指把页(整个地址空间的一部分)放到swap区。而“swap out”是指把整个地址空间放到swap区。可是它们有时候能够交换使用。
大部分被回收和进程地址空间的页缓存的回收取决于其使用场景。并将对性能产生影响。
你能够通过使用/proc/sys/vm/swappiness对该行为进行一些控制。
swap(交换区)
如前所述,当页回收发生时,在非活动列表中属于该进程地址空间的候选页将会被page out。发生交换本身并不意味着发生了什么状况。
尽管在其它系统中,swap仅仅只是是万一发生了主要内存的过度分配的一种保障,可是Linux更有效地使用swap空间。
如图1-12所看到的。虚拟内存由物理内存和磁盘或者swap分区共同组成。在Linux的虚拟内存管理的实现中,假设一个内存页已经被分配,可是在一段时间内都没有被使用。Linux会把该内存页移动至swap空间中。
你常常能够看到如getty的守护进程,它们通常当系统启动时被启动。但差点儿不被使用。释放页所占的珍贵的主内存并把它移至交换区似乎是更加高效的。
这正是Linux管理swap的方式,因此当你发现交换区已经使用了50%并不需要惊慌。其实,swap空间開始被使用并不意味着内存瓶颈;相反地。它证明了Linux怎样高效地管理系统资源。