在项目debug时发现log中经常不断的触发lowemeory killer(以后简称LMK)机制去kill掉一些进程,后查明是在sharefolder时候配置init.qcom.post_boot.sh对LMK门限值设定出现遗漏,导致阀值过高,以至于LMK长期被触发,并占用了大量内存系统资源,浪费进程空间。让上层同事对此造成误会,特对此Memorykill做出简要描述。
Android Kernel会定时执行一次对内存的检查,如果达到一定阀值,则杀死一些进程,释放其内存,采用的就是Low memory kille机制。
LMK在计算kill进程时主要是通过进程的oom_adj值来判定进程的重要程度。这个值越小,程序越重要,被杀的可能性越低。
Low memory killer源码和具体实现可参看:kernel/drivers/misc/lowmemorykiller.c
2.1 LMK逻辑流程:
a.LMK开始工作时,首先根据阈值表确定当前的警戒级数,则高于警戒级数的进程是待杀的范围。
b.然后遍历所有进程的oom_adj值,找到大于min_adj的进程,若找到多个,则把占用进程最大的进程存放在selected中。
c.最后也是关键的一步就是,发送SIGKILL信息,杀掉该进程。
oom_adj的大小和进程的类型以及进程被调度的次序有关。
Oom_adj在对进程类型进行分类的规则,可以在ActivityManagerService中清楚的看到:
3. staticfinal int EMPTY_APP_ADJ;
4. staticfinal int HIDDEN_APP_MAX_ADJ;
5. staticfinal int HIDDEN_APP_MIN_ADJ;
6. staticfinal int HOME_APP_ADJ;
7. staticfinal int BACKUP_APP_ADJ;
8. staticfinal int SECONDARY_SERVER_ADJ;
9. staticfinal int HEAVY_WEIGHT_APP_ADJ;
10. staticfinal int PERCEPTIBLE_APP_ADJ;
11. staticfinal int VISIBLE_APP_ADJ;
12. staticfinal int FOREGROUND_APP_ADJ;
13. staticfinal int CORE_SERVER_ADJ = -12;
14. staticfinal int SYSTEM_ADJ = -16;
ActivityManagerService定义各种进程的oom_adj,CORE_SERVER_ADJ代表一些核心的服务的omm_adj,数值为-12,这类进程永远也不会被杀死(异常crash除外)。
其他未赋值的都在static块中进行了初始化,是通过system/rootdir/init.rc进行配置的,其配置信息如下:
在init.rc中:
15.# Define theoom_adj values for the classes of processes that can be
16.# killed by thekernel. These are used in ActivityManagerService.
17. setpropro.FOREGROUND_APP_ADJ 0
18. setpropro.VISIBLE_APP_ADJ 1
19. setpropro.SECONDARY_SERVER_ADJ 2
20. setpropro.HIDDEN_APP_MIN_ADJ 7
21. setpropro.CONTENT_PROVIDER_ADJ 14
22. setpropro.EMPTY_APP_ADJ 15
23.
24.# Define the memorythresholds at which the above process classes will
25.# bekilled. These numbers are in pages (4k).
26. setpropro.FOREGROUND_APP_MEM 1536
27. setpropro.VISIBLE_APP_MEM 2048
28. setpropro.SECONDARY_SERVER_MEM 4096
29. setpropro.HIDDEN_APP_MEM 5120
30. setpropro.CONTENT_PROVIDER_MEM 5632
31. setpropro.EMPTY_APP_MEM 6144
32.
而设计到LMK的配置文件有如下三个:
a) /sys/module/lowmemorykiller/parameters/adj
b) /sys/module/lowmemorykiller/parameters/minfree
c) Init.qcom.post_boot.sh
owmeme_adj:中各项数值代表阈值的警戒级数,
lowmem_minfree:代表对应级数的剩余内存。
Init.qcom.post_boot.sh:中可以配置Lmk不同阶段阀值大小。该文件适用于整机优化内容。而对于某些小内存设备,也可以手动调整对应的门限值,例如:
一般调整后三个值。
echo“1536,2048,4096,15360,17920,20480″>/sys/module/lowmemorykiller/parameters/minfree
而adj文件存放着oom_adj 内存警戒值( 以4K为单位)
cat到底信息如下:
0 1536
1 2048
2 4096
7 5120
14 5632
15 6144
上述参数的含义,当系统的剩余内存为小于6MB时候,警戒级数为0,当系统内存剩余小于8M而大于
6M的时候,警戒级数为1,当内存小于64M大于16MB的时候,警戒级数为12.
在init中可以找到如下配置:
# Write value mustbe consistent with the above properties.
write/sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15
write/proc/sys/vm/overcommit_memory 1
write/sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144
进程oom_adj同样可以进行设置,通过write /proc/
#Set init its forked children's oom_adj.
write/proc/1/oom_adj -16
dumpsys activity可以dump进程的信息,查看adj值。procrank可以查看进程占用内存大小,当然也可以使用top或者cat mininfo等节点确定。
源码位于: oom_kill.c