LowMemoryKiller
adb命令:
>adb root
restarting adbd as root
>adb shell cat sys/module/lowmemorykiller/parameters/minfree
18432,23040,27648,32256,55296,80640
>adb shell cat sys/module/lowmemorykiller/parameters/adj
0,100,200,300,900,906
对于这两个文件的理解,其实质上是配合使用的,minfree里面的数字是表示内存剩余大小80640表示80640*4/1024=315M,而adj中的则表示进程对应的优先级;
即:当内存不足低至315M时,系统就会杀掉进程优先级大于906的进程;
如何查看每个进程的优先级呢?
方案1:
dumpsys activity processes |grep -e set= -e ‘* UID’
可获取如下 结果,其中set值即为adj值
APP UID 10035 ProcessRecord{99ade8b 16686:android.process.acore/u0a35}
oom: max=1001 curRaw=902 setRaw=902 cur=902 set=902
APP UID 10018 ProcessRecord{714580f 2907:android.process.media/u0a18}
oom: max=1001 curRaw=902 setRaw=902 cur=902 set=902
方案2:
通过命令adb shell ps 或者adb shell ps |findstr 进程pid 的方式,可以查看所有进程\指定进程的pid
在系统目录 /proc/下,会有每个进程的文件夹
以进程pid=2528为例,
proc/2528 # ls |grep oom
oom_adj (代表进程的优先级, 数值越大,优先级越低,越容易被杀. 取值范围[-16, 15])
oom_score ( lmk策略中没有看到使用的地方,应该是oom才会使用。 要想提高进程优先级,尽量避免自己被杀,那就得提高进程的oom_score_adj)
oom_score_adj (取值范围[-1000, 1001] ,该值就是AMS设置过来的值, 值定义见ProcessList.java )
高版本的内核都不在使用oom_adj,而是用oom_score_adj,oom_score_adj是一个向后兼容。
综上所述,oom_score_adj 对应的之前提到的kill进程的优先级
adb shell cat sys/module/lowmemorykiller/parameters/adj
0,100,200,300,900,906
-
若要获取所有进程的adj值,可观察proc下文件类型,根据需求,若要杀应用进程,一般只需要查看四位数字的文件夹即可。
-
考虑到proc下文件系统访问需要root权限(在此我们默认为系统源码级开发),我们可以用shell脚本来执行获取数据。
-
shell脚本放哪呢? 通过查看系统文件,发现vendor/bin和system/bin下有很多sh文件,于是,我们可以把sh文件放在更容易操作的system/bin目录下
-
sh文件如何执行呢?我们把sh文件命名为adj.sh. 可以简单的通过adb命令来执行,adb shell adj.sh,作为代码实现执行,可以通过创建rc文件,在rc文件中定义,写系统属性的时候,执行sh。
adj.sh 可参考如下示例,根据需求进行修改
解释如下:
- 在sdcard下创建临时文件adj_temp_result.txt
- 将开始和结束时间写入文件的开头和结尾,以便查看本次命令执行开始时间和耗时
- 通过执行ls /proc/[0-9]???/oom_score_adj 的方式,获取所有四位id 的oom_score_adj 路径
- 遍历以上路径,输出oom_score_adj 值和路径,每行格式如:-800/proc/1947/oom_score_adj,从整个文件获取列表,每行第一位是oom_score_adj 值,第三位是pid值。
- echo输出到文件时,单个>清除文件内容,从文件开头写入,>>代表追加内容到文件尾
#!/bin/sh
touch /sdcard/adj_temp_result.txt
current_time=$(date "+%Y-%m-%d %H:%M:%S.sss")
echo $current_time>/sdcard/adj_temp_result.txt
for line in $(ls /proc/[0-9]???/oom_score_adj)
do
echo $(cat $line)/$line >>/sdcard/adj_temp_result.txt
done
current_time=$(date "+%Y-%m-%d %H:%M:%S.sss")
echo $current_time>>/sdcard/adj_temp_result.txt
rc和sh的使用
Android.mk 中添加
LOCAL_INIT_RC := adj.rc
$(shell cp -f $(LOCAL_PATH)/adj.rc $(PRODUCT_OUT)/system/etc/init/)
$(shell cp -f $(LOCAL_PATH)/adj.sh $(PRODUCT_OUT)/system/bin/)
adj.rc 如下, 设置系统属性vendor.zw.adj=1 时,执行设为root权限的adj.sh
on property:vendor.zw.adj=1
start adj-sh
#delete log client
service adj-sh /system/bin/adj.sh
class main
user root
group root
disabled
oneshot
以上cp命令也可放在增删模块的mk文件中添加
PRODUCT_COPY_FILES +=
packages/apps/xxx/adj.sh:KaTeX parse error: Undefined control sequence: \ at position 37: …EM)/bin/adj.sh \̲ ̲ package…(TARGET_COPY_OUT_SYSTEM)/etc/init/adj.rc
此外,还需要配置adj.sh 的selinux 权限,请参照工程源码中的其他例子
修改file_contexts 和自己新增的te文件