转载请注明链接
由于Android的内存管理机制,在开发过程中常见的两种内存回收杀死App情况有以下两种:
内存紧张时LowMemoryKiller杀死。
空闲进程被AMS杀死。
定制手机ROM时,开发人员可能并不想让自己的预装应用被以上两种机制杀死,可以采用添加内存白名单的方式防止系统对预装应用进行回收处理。
// 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,并调整对应的内存阈值。
具体实现/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……
待续