LMK(Low Memory Killer)

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内存大小来杀掉对应的进程。


LMK(Low Memory Killer)_第1张图片

LMK(Low Memory Killer)_第2张图片

LMK(Low Memory Killer)_第3张图片

查看设备的内存临界值

我们可以通过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/


博主另一篇详细分析

Android LowMemoryKiller ADJ


你可能感兴趣的:(Android,零碎知识记录,LMK)