lowmemkiller的实现机制
lowmemkiller.c会在驱动初始化时注册一个shrinker到系统的shrinker_list中
165 static struct shrinker lowmem_shrinker = { 166 .shrink = lowmem_shrink, 167 .seeks = DEFAULT_SEEKS * 16 168 }; 169 170 static int __init lowmem_init(void) 171 { 172 register_shrinker(&lowmem_shrinker); 173 return 0; 174 }
166 lowmem_shrink是lowmemkiller机制的主函数
167 seeks参数,表示重建这个对象所需要花费的代价,这个因子越大,那么shrinker所要执行shrinke次数越多。
172 通过register_shrinker注册到系统的shrinker_list中,这样在kswapd或者try_to_free_pages就有可能调到lowmem_shrink函数
lowmem_shrink函数会首先找到满足条件的进程
最后调用SIGKILL杀死进程。
调用lowmemkiller的时机
lowmem_shrinker处理函数通过register_shrinker(&lowmem_shrinker)注册到系统的shrinker_list中。shirker_list是一个shrinker链表的表头,在shrink_slab中会执行这个链表中的每一个shinker函数。
shrinker_slab会被do_try_to_free_pages或者balance_pgdat中调用,shrinker函数和slab不是一定相关的,之所以使用shrinker_slab这个名字,是因为早期仅仅slab类型的cache需要被shrink。
如何设置应用程序的oom_adj
有以下方法可以设置进程的oom_score_adj
注意,方法2设置的oom_score_adj是根据应用进程的类型进程设置的,没有办法对oom_score_adj进行定制。
lowmemkiller的现存问题
在lowmemkiller.c源代码有如下注释:
* The driver considers memory used for caches to be free, but if a large * percentage of the cached memory is locked this can be very inaccurate * and processes may not get killed until the normal oom killer is triggered.
lowmemkiller驱动把cache占用的memory计算到空闲空间里面,但是如果这些cached的内存都被lock住,那么实际上这些内存是无法被内核回收的,也就是说这些内存并不是空闲的,因此空闲空间的统计数据被夸大了。