lowmemorykiller总结

2018-01-07  本文已影响359人  Stan_Z

版权声明:本文为作者原创,转载必须注明出处。
转载请注明出处:https://www.jianshu.com/p/09922ab0390b

我们知道,从zygote孵化出来的进程都会记录在ActivityManagerService.mLruProcesses列表中,由ActivityManagerService进行统一管理,ActivityManagerService核心业务之一便是时时更新进程的状态,根据状态计算出进程对应的OomAdj值,这个值会传递到kernel中去,kernel有个低内存回收机制,在内存达到一定阀值时会触发清理OomAdj值高的进程,这边是Lowmemorykiller工作原理。

首先来看一下整体的流程:

我们都知道,AMS负责了系统中四大组件的启动、切换、调度以及应用进程管理和调度工作。在APP使用过程中,AMS会根据四大组件关键生命周期,在mLruProcesses中时时地设定对应进程的adj值(更新进程优先级),在内存低于lowmemorykiller杀进程的阈值时,lowmemorykiller会选择adj优先级最大(如果adj相等选择同adj中内存占用最大)的进程杀掉,释放内存。

其次,了解下定义在ProcessList.java文件的ADJ级别,oom_adj划分为16级,从-17到16之间取值。越大优先级越低

ADJ级别 取值 解释
UNKNOWN_ADJ 16 一般指将要会缓存进程,无法获取确定值
CACHED_APP_MAX_ADJ 15 不可见进程的adj最大值
CACHED_APP_MIN_ADJ 9 不可见进程的adj最小值
SERVICE_B_ADJ 8 B List中的Service(较老的、使用可能性更小)
PREVIOUS_APP_ADJ 7 上一个App的进程(往往通过按返回键)
HOME_APP_ADJ 6 Home进程
SERVICE_ADJ 5 服务进程(Service process)
HEAVY_WEIGHT_APP_ADJ 4 后台的重量级进程,system/rootdir/init.rc文件中设置
BACKUP_APP_ADJ 3 备份进程
PERCEPTIBLE_APP_ADJ 2 可感知进程,比如后台音乐播放
VISIBLE_APP_ADJ 1 可见进程(Visible process)
FOREGROUND_APP_ADJ 0 前台进程(Foreground process)
PERSISTENT_SERVICE_ADJ -11 关联着系统或persistent进程
PERSISTENT_PROC_ADJ -12 系统persistent进程,比如telephony
SYSTEM_ADJ -16 系统进程
NATIVE_ADJ -17 native进程(不被系统管理)

然后,我们要了解两个问题:
1)阈值是怎么设定的?

AMS updateConfiguration方法是设定阈值的入口,在AMS初始化时执行一次,通过调用ProcessList中updateOomLevels方法,计算出阈值adj 和 minfree 并通过Lmkd.c写入文件中保存。

2)adj的更新流程是怎样的?

AMS调整进程的adj有3大护法:

总结为如下表格:

AMS ProcessList lmkd.c 描述
applyOomAdjLocked setOomAdj LMK_PROCPRIO 设置进程adj
updateConfiguration updateOomLevels LMK_TARGET 更新oom_adj
cleanUpApplicationRecordLocked/handleAppDiedLocked remove LMK_PROCREMOVE 移除进程
Lmkd.c 对应方法 执行动作
LMK_PROCPRIO cmd_procprio 写/proc/<pid>/oom_score_adj
LMK_TARGET cmd_target 写/sys/module/lowmemorykiller/parameters/minfree写/sys/module/lowmemorykiller/parameters/adj
LMK_PROCREMOVE cmd_procremove 删除/proc/<pid>

查看系统阀值: adb shell cat /sys/module/lowmemorykiller/parameters/minfree

18432,23040,27648,32256,55296,80640
以上数字的单位是page. 1 page = 4 kb
对应的就是(MB): 72,90,108,216,216,315

为了更直观地了解执行流程,以applyOomAdjLocked过程为例,以下是时序图:

最终通过lowmemorykiller.c的核心方法:lowmen_scan执行杀进程:
监测到当前内存低于系统阈值(取出保存的minfree做对比),则会在大于等于该阈值的adj中寻找最大的(读取/proc/<pid>/oom_score_adj每个进程的adj值),出现相等的情况,则挑选内存占用最大的进程作为kill的目标,最终通过信号将其杀掉。

此文抛砖引玉,目的只是简单介绍lowmemorykiller的执行原理和流程,并没有贴代码也没有一行行地去抠代码细节,目的是梳理下框架,也是作为一个备忘的小总结。

想详细了解lowmemorykiller的朋友推荐看看以下博文:
http://gityuan.com/2016/09/17/android-lowmemorykiller/
http://blog.csdn.net/happylishang/article/details/54408733

上一篇下一篇

猜你喜欢

热点阅读