内存白名单策略

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39694445/article/details/78300870

转载请注明链接

由于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回收:

待续

展开阅读全文

没有更多推荐了,返回首页