内存白名单策略

来源:互联网 发布:it软件开发培训班 编辑:程序博客网 时间:2024/05/01 23:02

  • 重要数组
  • 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回收:

待续