内核里控制脏页的参数

内核的脏页的控制分为时空两个大的维度。

在时间上脏页不能存在时间过长,过长会导致内存紧张。同时如果时间过长,这时候突然掉电,那么会导致数据损失过多。所以,无论如何都要有个时间的限制。

在空间上脏页不能太多,太多也会导致内存紧张。

在时间控制上总要的参数有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交换的就比较多,适用于进程分配大内存且读写频繁。

 

综上,上面的参数搜没有最合适的值,需要根据场景做设置。

猜你喜欢

转载自blog.csdn.net/xiaofeng_yan/article/details/81740512