现在的位置: 首页 > 综合 > 正文

lowmemorykiller的几点思考

2013年02月13日 ⁄ 综合 ⁄ 共 1593字 ⁄ 字号 评论关闭

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函数会首先找到满足条件的进程

  1. 获取当前系统的空闲内存,根据空闲内存数目,确定min_score_adj。
  2. 不是内核线程
  3. 进程和它的所有子进程都不拥有task_lock
  4. 进程的oom_score_adj大于min_score_adj
  5. 进程的oom_score_adj大于min_score_adj,并且和min_score_adj最相近
  6. 具有相同oom_score_adj,但是占用内存数量最大的进程

最后调用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

  1. 直接设置文件/proc/<pid>/oom_score_adj。设置为OOM_SCORE_ADJ_MIN会禁止oom杀掉这个进程
  2. 通过frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中的updateOomAdjLocked来设置进程的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住,那么实际上这些内存是无法被内核回收的,也就是说这些内存并不是空闲的,因此空闲空间的统计数据被夸大了。

抱歉!评论已关闭.