1.为什么要进行内存回收?
内核之所以要进行内存回收,主要原因有两个:
1)内核需要为任何时刻突发到来的内存申请提供足够的内存。所以一般情况下保证有足够的free空间对于内核来说是必要的。
2)另外,Linux内核使用cache的策略虽然是不用白不用,内核会使用内存中的page cache对部分文件进行缓存,以便提升文件的读写效率。
所以内核有必要设计一个周期性回收内存的机制,以便cache的使用和其他相关内存的使用不至于让系统的剩余内存长期处于很少的状态。
当真的有大于空闲内存的申请到来的时候,会触发强制内存回收。
2.内核在应对这两类回收的需求下,分别实现了两种不同的机制:
一个是使用 kswapd进程对内存进行周期检查 ,以保证平常状态下剩余内存尽可能够用。
另一个是 直接内存回收(directpagereclaim) ,就是当内存分配时没有空闲内存可以满足要求时,触发直接内存回收。
这两种内存回收的触发路径不同:
一个是由内核进程kswapd直接调用内存回收的逻辑进行内存回收;
参见mm/vmscan.c中的kswapd()主逻辑
另一个是内存申请的时候进入slow path的内存申请逻辑进行回收。
参见内核代码中的mm/page_alloc.c中的__alloc_pages_slowpath方法
这两个方法中实际进行内存回收的过程殊途同归,最终都是 调用shrink_zone() 方法进行针对每个zone的内存页缩减。
Kswapd是linux中用于页面回收的内核线程。
页面回收,并不是回收得越多越好,而是力求达到一种balanced。因为页面回收总是以cache丢弃、内存swap、等为代价的,对系统性能会有一定程度的影响。而balanced,就是既要保证性能,又要应付好新来的页面分配请求。