Android low memory killer 详解

Android在内存管理上与linux有些小的区别。其中一个就是引入了Low memory killer .

1,引入原因

Android是一个多任务系统,也就是说可以同时运行多个程序,这个大家应该很熟悉。一般来说,启动运行一个程序是有一定的时间开销的,因此为了加快运 行速度,当你退出一个程序时,Android并不会立即杀掉它,这样下次再运行该程序时,可以很快的启动。随着系统中保留的程序越来越多,内存肯定会出现 不足,low memory killer就是在系统内存低于某值时,清除相关的程序,保障系统保持拥有一定数量的空闲内存。

2,基本原理和重要概念

Low memory killer根据两个原则,进程的重要性和释放这个进程可获取的空闲内存数量,来决定释放的进程。

(1)进程的重要性,由task_struct->signal_struct->oom_adj决定。

Android将程序分成以下几类,按照重要性依次降低的顺序:

名 称 oom_adj 解释
FOREGROUD_APP 0 前 台程序,可以理解为你正在使用的程序
VISIBLE_APP 1 用户可见的程序
SECONDARY_SERVER 2 后 台服务,比如说QQ会在后台运行服务
HOME_APP 4 HOME,就是主界面
HIDDEN_APP 7 被 隐藏的程序
CONTENT_PROVIDER 14 内容提供者,
EMPTY_APP
15
空程序,既不提供服务,也不提供内容


其中每个程序都会有一个oom_adj值,这个值越小,程序越重要,被杀的可能性越低。

(2)进程的内存,通过get_mm_rss获取,在相同的oom_adj下,内存大的,优先被杀。

(3)那内存低到什么情况下,low memory killer开始干活呢?Android提供了两个数组,一个lowmem_adj,一个lowmem_minfree。前者存放着oom_adj的阀值,后者存放着minfree的警戒值,以page为单位(4K)。

oom_adj 内存警戒值( 以4K为单位)
0 1536
1 2048
2 4096
7 5120
14 5632
15 6144

3,源码解析

module_init(lowmem_init);
module_exit(lowmem_exit);

模块加载和退出的函数,主要的功能就是register_shrinker和unregister_shrinker结构体lowmem_shrinker。主要是将函数lowmem_shrink注册到shrinker链表里,在mm_scan调用。

下面详细的介绍这个函数:

for (i = 0; i < array_size; i++) {
if (other_file < lowmem_minfree[i]) {
min_adj = lowmem_adj[i];
break;
}
}

other_file,系统的空闲内存数,根据上面的逻辑判断出,low memory killer需要对adj高于多少(min_adj)的进程进行分析是否释放。

if (nr_to_scan <= 0 || min_adj == OOM_ADJUST_MAX + 1) {
lowmem_print(5, "lowmem_shrink %d, %x, return %d/n",
nr_to_scan, gfp_mask, rem);
return rem;
}

判断,系统当前的状态是否需要进行low memory killer。

for_each_process(p) {
struct mm_struct *mm;
struct signal_struct *sig;
int oom_adj;

task_lock(p);
mm = p->mm;
sig = p->signal;
if (!mm || !sig) {
task_unlock(p);
continue;
}
oom_adj = sig->oom_adj;
if (oom_adj < min_adj) {
task_unlock(p);
continue;
}
tasksize = get_mm_rss(mm);
task_unlock(p);
if (tasksize <= 0)
continue;
if (selected) {
if (oom_adj < selected_oom_adj)
continue;
if (oom_adj == selected_oom_adj &&
tasksize <= selected_tasksize)
continue;
}
selected = p;
selected_tasksize = tasksize;
selected_oom_adj = oom_adj;
lowmem_print(2, "select %d (%s), adj %d, size %d, to kill/n",
p->pid, p->comm, oom_adj, tasksize);
}

对每个sig->oom_adj大于min_adj的进程,找到占用内存最大的进程存放在selected中。

if (selected) {
if (fatal_signal_pending(selected)) {
pr_warning("process %d is suffering a slow death/n",
selected->pid);
read_unlock(&tasklist_lock);
return rem;
}
lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d/n",
selected->pid, selected->comm,
selected_oom_adj, selected_tasksize);
force_sig(SIGKILL, selected);
rem -= selected_tasksize;
}

发送SIGKILL信息,杀掉该进程。

4,配置

通过下面两个文件,/sys/module/lowmemorykiller/parameters/adj和/sys/module/lowmemorykiller /parameters/minfree配置系统的相关参数。

更多相关文章

  1. Android应用程序进程启动过程的源代码分析
  2. 浅析Android线程模型
  3. 图解Android和Linux发行版的区别
  4. apk反编译
  5. Android(安卓)应用程序开发基础
  6. android framework 启动流程
  7. Android(安卓)-- Android(安卓)Init进程的处理流程分析
  8. Android应用程序进程启动过程的源代码分析(1)
  9. Android(安卓)App 性能优化之图片优化

随机推荐

  1. Android(安卓)自定义控件之图片裁剪
  2. Android(安卓)SmsManager(短信管理器),发送
  3. android MediaRecorder 视频录制
  4. Android(安卓)sensor介绍
  5. Android摄像头视频帧数据测试代码
  6. Ubuntu 14.04 配置Android编译环境
  7. android 获取网络图片
  8. Android中Parcelable接口用法
  9. android 性能优化
  10. android drawable 使用shape实现复杂图像