测试环境

设备:Sony Xperia XZ Premium (docomo版本)
版本:官方Android 9.0
内核版本:4.4.302
版本号:47.2.E.3.29
(该设备USB烧了,所以日志全靠开机脚本抓取。。。)

前言

以下内容仅作为本人做记录,估计也不会有人花大时间折腾旧设备

过年前有点空,寻思可能有机会要在25年拿xzp做主力机一段时间,于是重新倒腾了下。然后发现app在解压文件时会闪退,查日志发现被simple lmk干掉了。此时想起来以前在群里讨论lmk相关时有人说后续android用PSI配合LMKD解决了传统LMK乱杀的问题。于是看了下谷歌的文档万恶之源
低内存终止守护程序
PSI只向后移植到了4.9,也就是我手头的4.4还得再backport一遍。原本以为两天搞定,结果发现坑越挖越大,到了除夕还没搞完。。。

正常人谁大年三十修内核啊


大致流程

内核部分

对照android-common的4.9分支,kernel/sched/psi.c部分前前后后一些commit自行pick后修复,正常情况下开启后会有nodes在/proc/pressure下,并且可以对其写入。写入参考DOC

系统部分

需要使用高版本android的lmkd,在不改变lmkd.rc和android版本的情况下搞了个旧版本pick新特性的lmkd_androidQ
扔aosp源码里编译然后拿出来用。

selinux部分

magisksepolicy添加规则解决,不知道为啥我这放sepolicy.rule没生效,改为脚本添加了。参考我xzp源码psi分支模块中post-fs-data脚本。


遇到的坑

这才是主体(

  • 最大的坑就是谷歌的文档,要不是文档里写的“ Android 9 及更高”我压根就不会去倒腾

  • 文档的小标题是“在 Android 10 中使用用户空间 lmkd”,但是下面又写“在 Android 9 及更高版本中,用户空间 lmkd 会在未检测到内核中的 LMK 驱动程序时激活。”
    虽然它标题写了10,但是文中又写了9及更高。不知道为什么带上9,所以我认为的是在9上关闭内核的lmk后lmkd也会激活。结果我关了之后直接不开机了。看了下lmkd.rc才发现服务是critical,启动失败直接bootloop。再看dmesg,只看到了服务退出代码1。
    当时忘了lmkd不是内核的玩意,没看logcat,过阵子才想起来这个事。翻日志发现是因为vmpressure也不支持所以直接退出了,vmpressure在lmkd源码中依赖于memcg,原机内核没开。开完了先试试lmkd+vmpressure的效果,结果是开机后杀疯了,启动器被杀的反复重启,寻思反正也不用这玩意还是去看看PSI。。。

  • Android9的PSI并不支持LMKD,所以需要用10的。lmkd源码单独拿ndk编译没搞定,不想拉几百G的aosp,正好手头xperia8是A10,提取了一下。结果发现用不了,有个函数缺了。但是看这函数是log相关,去掉了也无伤大雅(
    这个时候就该上万能的LD_PRELOAD了,写个同名空函数,用ndk编译成so文件,带上LD去执行发现能用。但最终不是在终端运行,而是在服务中运行,所以问题就来了。
    rc中我改全局init.environment.rc带上这玩意会炸系统,暂时不知道原因。单service中没看到能带环境的,gpt给我的全是不能用的。那寻思搞不定就用sh脚本吧,sh脚本又不能作为class core启动。。。
    那没办法了,随手写了个LMKD-wrapper,编译成可执行文件,扔进去能用,毕竟这不是重点,重点还是正常用PSI。(代码xjb写的,后面都直接重编译lmkd源码了索性就不用这个wrapper了)

  • /proc/pressure/memory能读不能写。一开始log中lmkd一直报写入失败是没权限,我还以为是内核的问题,又pick+移植了一堆前置commit发现还是没解决。(此处又被gpt坑了,gpt给我的测试写入的参数完全不对,后面看doc中的才正常)。然后写入炸了,直接卡死。没usb没办法抓崩溃日志,放xperia8上由于炸崩了也没抓到,又开了一些debug抓到了,kthread相关函数签名变化了,好歹有log才能修。

  • 写入解决了,A10上的LMKD也能用了,开机测试,然后发现直接不开机了。再看log,杀进程杀得比vmpressure还猛。oom得分为0的都杀了,日志里还一直是找不到新的进程去kill。。。看了下lmkd的逻辑,部分PSI阈值70以上算压力过大,大法官方系统太过臃肿,zram要开机后才会创建。开机过程中压力就90+,所以猛杀。但是根据谷歌文档,PSI那部分能手动调的参数要在android11上的lmkd,android10上的还不支持。。。。。
    被迫拉aosp源码,淦一个船新版本的lmkd出来。由于一些新更改要修改lmkd.rc,我认为magisk下替换原有rc还是复杂了点,要放boot中。涉及到lmkd.rc的更改也不是重要的功能性,直接drop。淦完后配合ro.config.low_ram设置就正常了(4g大法那是真算低内存设备)。

  • 最后就是selinux问题了,由于我xzp的官方系统被我魔改过,selinux开机就设为permissive。但是psi的nodes相关se权限是在A10才引入的。所以参照google的sepolicy源码,把相关条目用magisksepolicy注入进去,lmkd去访问就正常了。


后记

目前在xzp上测的没啥问题,xperia8上倒是过一段时间就卡死,抓取日志在卡死之前就停了,目测lmkd把某个关键进程杀了。