Low Memory Killer
进程按照状态分完重要性之后,就要开始杀进程了。Android的Low Memory Killer基于Linux的OOM机制,在Linux中,内存是以页面(page)为单位,当申请页面分配不足的时候,系统会通过Low Memory Killer来杀掉bad进程,释放内存。Low Memory Killer会根据进程的adj级别以及所占的内存,来决定是否杀掉该进程,adj越大,占用内存越多,进程越容易被杀掉。
关于adj的分级,我们可以参考ProcessList.java,这里面的常量定义了ADJ的分级。(7.0以后的adj分级与之前的不太一样(Processlist.java-Nougat),这个我们后续可以研究一下具体的改动是什么)
adj分级:
UNKNOWN_ADJ = 16
级别最低级的进程,通常是被缓存的进程,但是系统也不清楚缓存的内容。CACHED_APP_MAX_ADJ = 15
这是一个只托管不可见的活动的进程,因此可以在没有任何中断的情况下被杀死。CACHED_APP_MIN_ADJ = 9
缓存进程,没有英文解释。SERVICE_B_ADJ = 8
不活跃的服务,不想adj=5的服务那么活跃。
PS:这里说一句,在root以后,有的系统优化大师,会把所有服务统一调成adj=8这个级别,来达到内存优化的目的,后面我们会说到。PREVIOUS_APP_ADJ = 7
被切换的进程,一般是用户前一个使用的进程。两个应用来回切换,那么前一个应用一般adj设置为7。HOME_APP_ADJ = 6
与主应用程序有交互的进程。SERVICE_ADJ = 5
活跃的服务进程。HEAVY_WEIGHT_APP_ADJ = 4
高权重进程BACKUP_APP_ADJ = 3
正在备份的进程PERCEPTIBLE_APP_ADJ = 2
可感知进程(通常是前台Service进程)VISIBLE_APP_ADJ = 1
可见进程FOREGROUND_APP_ADJ = 0
前台进程
剩下的就是adj值为负数的进程,基本上都是系统集成,不在本文的讨论范围内。负数进程是不会被lmk杀掉的。
如何查看进程优先级
首先通过 adb shell ps 指令查找对应进程的pid
然后通过 adb shell cat /proc/${pid}/oom_adj(设备需要root)返回对应进程的adj值。
还可以把oom_adj替换成oom_score或者oom_score_adj来查看这两项的数值,当oom_adj相同时,LowMemoryKiller会根据oom_score_adj和RSS内存大小来杀掉对应的进程。
![\](https://www.2cto.com/uploadfile/Collfiles/20160720/20160720090809679.png)
查看设备的内存临界值
我们可以通过adb shell cat 查看下面两个文件
/sys/module/lowmemorykiller/parameters/adj
/sys/module/lowmemorykiller/parameters/minfree
(这里请注意,这两个文件是只可以写入的,cat之前请先用chmod赋予权限。)
adj 代表的是oom_score_adj的值,对应的minfree则代表内存临界值。
比如我的测试机小米4C测试机对应的值就是:
adj: 0,58,117,176,529,1000
这个值其实是oom_score_adj的值,用这个值*17再除1000四舍五入取整数,就是对应的adj的值,例如第二个值58即为 58*17/1000 = 1,对应的adj也就是1,所以这6个值对应的adj是0,1,2,3,9,15。1000默认就是15
minfree: 18432,23040,27648,32256,56250,81250
这个值是页值,一页等于4KB,换算成MB大概是72,90,108,126,220,318
当可用内存小于318MB的时候,系统开始杀adj=15的进程,以此类推。
驱动对应节点
// 获取了上面processlist 里面传下来的两个 策略数组 然后write到文件节点中
//#define INKERNEL_MINFREE_PATH "/sys/module/lowmemorykiller/parameters/minfree"
//#define INKERNEL_ADJ_PATH "/sys/module/lowmemorykiller/parameters/adj"
//驱动中对应的 文件节点
CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES 支持动态改 策略阀门 值。
另外注册了文件ops 以及节点 adj .minfree 分别与lowmem_adj . lowmen_minfree 数组成对应关系
策略数组以及阀值,两个数组之间也是一一对应关系,当内存小于64M时 就去准备 kill adj >=12 的process,取最低优先级 先kill, 比如此时有3个进程分别为 12 12 14 ,那么首先kill掉的是 14 ,kill之后还是少于64M 那么两个12 adj之间,先杀占用高的(参考 http://blog.csdn.net/jscese/article/details/47317765)
多进程使用场景可参考:
http://blog.spinytech.com/2016/11/17/android_multiple_process_usage_scenario/
博主另一篇详细分析