min_free_kbytes的初始化
min_free_kbytes的作用
当请求分配内存时,如果有足够的内存,则分配成功。如果没有,则要阻塞,释放内存,再来分配内存。原子请求不能被阻塞,如果分配不到,则失败。内核为了尽量避免原子请求失败,预留了一个页池框,在内存不足时使用。这个页池框的大小就是min_free_kbytes。
这段引自《深入理解Linux内核(第三版)(中文版)》Page302
min_free_kbytes的设置
代码调用关系
在init_per_zone_wmark_min()(\linux\mm\page_alloc.c) 中进行初始化,dump_stack()的结果:
[ 0.053007] [init_per_zone_wmark_min 6792] min_free_kbytes: 1024.
[ 0.053067] [<c0210710>] (unwind_backtrace) from [<c020bb54>] (show_stack+0x10/0x14)
[ 0.053083] [<c020bb54>] (show_stack) from [<c04fc8bc>] (dump_stack+0x84/0x98)
[ 0.053100] [<c04fc8bc>] (dump_stack) from [<c0e33870>] (init_per_zone_wmark_min+0x2c/0x13c)
[ 0.053127] [<c0e33870>] (init_per_zone_wmark_min) from [<c0201898>] (do_one_initcall+0x54/0x190)
[ 0.053153] [<c0201898>] (do_one_initcall) from [<c0e00e74>] (kernel_init_freeable+0x158/0x1e4)
[ 0.053180] [<c0e00e74>] (kernel_init_freeable) from [<c09b68d4>] (kernel_init+0x8/0x114)
[ 0.053203] [<c09b68d4>] (kernel_init) from [<c0208628>] (ret_from_fork+0x14/0x2c)
[ 0.053222] [init_per_zone_wmark_min 6797] nr_free_buffer_pages: 162930.
[ 0.053233] [init_per_zone_wmark_min 6798] lowmem_kbytes: 651720.
[ 0.053245] [init_per_zone_wmark_min 6802] new_min_free_kbytes: 3229.
[ 0.053256] [init_per_zone_wmark_min 6803] user_min_free_kbytes: -1.
[ 0.053267] [init_per_zone_wmark_min 6808] min_free_kbytes: 3229.
[ 0.053285] [init_per_zone_wmark_min 6822] min_free_kbytes: 3229.
代码流程就是:
kernel_init -- kernel_init_freeable -- do_one_initcall -- init_per_zone_wmark_min
代码逻辑
int min_free_kbytes = 1024; //初始值设为1024
int user_min_free_kbytes = -1;
int watermark_scale_factor = 10;
int __meminit init_per_zone_wmark_min(void)
{
unsigned long lowmem_kbytes;
int new_min_free_kbytes;
/*
nr_free_buffer_pages() 获取free_pages
根据公式 计算 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;
// min_free_kbytes必须在[128, 65536]之间
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);
}
......
}