内存白名单策略


  • 重要数组
  • LowMemoryKiller
  • 空闲进程AMS回收

转载请注明链接
由于Android的内存管理机制,在开发过程中常见的两种内存回收杀死App情况有以下两种:
内存紧张时LowMemoryKiller杀死。
空闲进程被AMS杀死。
定制手机ROM时,开发人员可能并不想让自己的预装应用被以上两种机制杀死,可以采用添加内存白名单的方式防止系统对预装应用进行回收处理。
1. 重要数组:
// These are the various interesting memory levels that we will give to // the OOM killer.Note that the OOM killer only supports 6 slots, so we // can't give it a different value for every possible kind of process.

在/frameworks/base/services/java/com/android/server/am/ProcessList.java文件中定义了如下三个数组:
  • 【内存白名单策略】Adj数组
    OOM killer仅支持6个slots,分别为:
//前台进程 static final int FOREGROUND_APP_ADJ = 0; //可见进程 static final int VISIBLE_APP_ADJ = 1; //可感知进程,如酷狗player的进程 static final int PERCEPTIBLE_APP_ADJ = 2; //备份进程 static final int BACKUP_APP_ADJ = 3; //空进程 static final int CACHED_APP_MIN_ADJ = 9; static final int CACHED_APP_MAX_ADJ = 15; private final int[] mOomAdj = new int[] { FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ, BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ };

  • 内存阈值数组
    各个进程level被杀死的内存阈值,android4.4已按照不同的设备类型给出了两类内存阈值数组.
private final long[] mOomMinFreeLow = new long[] { 8192, 12288, 16384, 24576, 28672, 32768 }; private final long[] mOomMinFreeHigh = new long[] { 49152, 61440, 73728, 86016, 98304, 122880 };

开发人员可根据自身设备的内存及App运行情况对上述两个数组自行调整。比如某个重要的App占用内存较多,需要常驻的后台服务,那么可以修改BACKUP_APP_ADJ——>SERVICE_ADJ,并调整对应的内存阈值。
2. LowMemoryKiller: 具体实现/drivers/staging/android/lowmemorykiller.c:
处理函数 lowmem_shrinker:
static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) { …… //循环遍历内存阀值数组,计算最小触发内存killer的adj值 for (i = 0; i < array_size; i++) { minfree = lowmem_minfree[i]; if (other_free < minfree && other_file < minfree) { min_score_adj = lowmem_adj[i]; break; } } selected_oom_score_adj = min_score_adj; …… // 循环遍历所有process,找出大于min_score_adj的process,筛选出oom_score_adj最大且占用内存最大的process,kill之 for_each_process(tsk) { …… p = find_lock_task_mm(tsk); oom_score_adj = p->signal->oom_score_adj; // 该process不满足上面找到的需要杀死process的最小adj,继续遍历 if (oom_score_adj < min_score_adj) { task_unlock(p); continue; } // 此处是白名单设定,重点关注 // 先判断是不是要回收VISIBLE_APP_ADJ级别之上的process,如果是,则不再判断白名单,因为此时内存已经非常紧张了。 if (min_score_adj >= BACKUP_APP_ADJ){ // 如果需要kill的process在VISIBLE_APP_ADJ级别之下,则判断该进程是否在白名单,如果是,不予kill if (is_in_whitelist(p->comm)) { task_unlock(p); continue; } }tasksize = get_mm_rss(mm); task_unlock(p); if (tasksize <= 0) continue; if (selected) { // 该process的oom_score_adj小于上个循环筛选出的adj,继续遍历 if (oom_score_adj < selected_oom_score_adj) continue; // 该process的内存占用小于上个循环筛选出的同adj的process,继续遍历 if (oom_score_adj == selected_oom_score_adj && tasksize <= selected_tasksize) continue; } selected = p; selected_tasksize = tasksize; selected_oom_score_adj = oom_score_adj; } //send SIGKILL杀死这个占用最大内存的process if (selected) { …… trace_lowmem_kill(selected,other_file, minfree, min_score_adj, other_free); lowmem_deathpending_timeout = jiffies + HZ; send_sig(SIGKILL, selected, 0); set_tsk_thread_flag(selected, TIF_MEMDIE); rem -= selected_tasksize; } }

如下代码为白名单过滤代码:
// 先判断是不是要回收VISIBLE_APP_ADJ级别之上的process,如果是,则不再判断白名单,因为此时内存已经非常紧张了。 if (min_score_adj >= BACKUP_APP_ADJ){ // 如果需要kill的process在VISIBLE_APP_ADJ级别之下,则判断该进程是否在白名单,如果是,不予kill if (is_in_whitelist(p->comm)) { task_unlock(p); continue; } } // 白名单whitelist.txt: com.company.packagename……

3. 空闲进程AMS回收: 待续

    推荐阅读