内核的脏页的控制分为时空两个大的维度。
在时间上脏页不能存在时间过长,过长会导致内存紧张。同时如果时间过长,这时候突然掉电,那么会导致数据损失过多。所以,无论如何都要有个时间的限制。
在空间上脏页不能太多,太多也会导致内存紧张。
在时间控制上总要的参数有dirty_expire_centisecs,linux后台的flush线程按照dirty_writeback_centisecs周期启动,这个线程会查看这个参数,如果超过时间,就会写回。注意,系统即使还有很多剩余的内存。比如只有1页脏页,但是这个脏页的时间超过了dirty_expire_centisecs,那么这个脏页也会被写回。默认是30S,经验值一般调成8S。
基于空间的参数是,dirty_background_ratio和dirty_ratio。当脏页达到一定的比例,系统就要回收脏页了。当达到dirty_background_ratio门阈值后,后台进程开始写回脏页。当达到dirty_ratio之后,会阻塞正在分配内存的进程,然后调用写回脏页的进程,
脏页写回不是内存回收。脏页控制防止内存脏页过多。
内存回收涉及的是几个水位的变化。
在/proc/sys/vm/min_free_kbytes ,有个公式,计算是和低端内存大小和求低端内存平方根有关系
/*
* Initialise min_free_kbytes.
*
* For small machines we want it small (128k min). For large machines
* we want it large (64MB max). But it is not linear, because network
* bandwidth does not increase linearly with machine size. We use
*
* min_free_kbytes = 4 * sqrt(lowmem_kbytes), for better accuracy:
* min_free_kbytes = sqrt(lowmem_kbytes * 16)
*
* which yields
*
* 16MB: 512k
* 32MB: 724k
* 64MB: 1024k
* 128MB: 1448k
* 256MB: 2048k
* 512MB: 2896k
* 1024MB: 4096k
* 2048MB: 5792k
* 4096MB: 8192k
* 8192MB: 11584k
* 16384MB: 16384k
*/
int __meminit init_per_zone_wmark_min(void)
{
unsigned long lowmem_kbytes;
int new_min_free_kbytes;
lowmem_kbytes = nr_free_buffer_pages() * (PAGE_SIZE >> 10);
new_min_free_kbytes = int_sqrt(lowmem_kbytes * 16);
if (new_min_free_kbytes > user_min_free_kbytes) {
min_free_kbytes = new_min_free_kbytes;
if (min_free_kbytes < 128)
min_free_kbytes = 128;
if (min_free_kbytes > 65536)
min_free_kbytes = 65536;
} else {
pr_warn("min_free_kbytes is not updated to %d because user defined value %d is preferred\n",
new_min_free_kbytes, user_min_free_kbytes);
}
setup_per_zone_wmarks();
refresh_zone_stat_thresholds();
setup_per_zone_lowmem_reserve();
#ifdef CONFIG_NUMA
setup_min_unmapped_ratio();
setup_min_slab_ratio();
#endif
return 0;
}
core_initcall(init_per_zone_wmark_min)
Low=5/4*min
High=6/4*min
当达到low,后台回收(kswap)内存。直到high为止。但是应用的程序要内存的速度大于回收的速度,那么就有可能达到min水位,这个时候应用会阻塞,然后内核直接会回收内存。直到回收够用为止(需要看代码,多大是够用)。然后应用程序会再次运行。如果还不够,就直接kill一个占用内存比较大的进程,通常都是这个这个应用程序。
回收是匿名页多点还是文件背景的page cache多点。这个是由swappiness决定的。当swappiness比较大的话,swap匿名页就多,此时page cache被交换的比较小,这个场景适用于希望文件速度读写比较快。如果swappiness比较小的话,那么page cache交换的就比较多,适用于进程分配大内存且读写频繁。
综上,上面的参数搜没有最合适的值,需要根据场景做设置。