LMK是Android在,手机内存不足的情况下,所做出的的应对机制,它是在OOM Killer 基础上修改而来的,当系统内存不足时,杀死不重要的进程以释放其内存。首先来看一下,当低内存时,会给手机的运行带来什么问题?
低内存时 Android 系统的工作机制
根据操作系统所学的知识:物理内存被分为很多页(Page),每页 4KB。通过对Page的读写来保证内存的正常使用。其中Pages如下图所示,分为使用的、未使用的、缓存的
在 Android的系统中,有专门用于回收 Cached pages 的 kswapd 进程:起作用为:
- 当 Free Pages 低于 kswapd 的阈值时,Linux 内核就会通过 kswapd 进程对 Cached Pages 进行回收,若此时想要访问Cached Pages里的内容,就只能从flash中加载,从而严重降低了手机运行的速度。
LMK
简介
通过上部分可以发现,Low Memory Killer在内存不足时显得尤为重要,其在 Cached Pages 低于阈值时被触发。其工作的原理为:是根据进程的优先级,选择性地杀死某个进程,释放该进程占用的所有资源以满足内存分配需要:早年间其进程的优先级大抵如下图所示:(其中Cached是退出后代的进程)通俗的理解为,当内存不够时,LMK会首先将Cached级别的进程杀死,以获得更多的缓存页,如Cached类别中没有其他进程,则会杀死之间的那个进程Android的设置,甚至是home进程(2020年了,已不存在,但模拟中会出现这种情况),产生黑屏现象。
工作原理
具体来讲,LMK是通过3个具体参数决定Kill那个进程的
- oom_adj:在 Framework 层使用,代表进程的优先级,数值越高,优先级越低,越容易被杀死。
- oom_adj threshold:在 Framework 层使用,代表 oom_adj 的内存阈值。Android Kernel 会定时检测当前剩余内存是否低于这个阀值,若低于则杀死 oom_adj ≥ 该阈值对应的 oom_adj 中,数值最大的进程,直到剩余内存恢复至高于该阀值的状态。
- oom_score_adj: 在 Kernel 层使用,由 oom_adj 换算而来,是杀死进程时实际使用的参数。
工作流程
- 启动 lmkd
lmkd 是由 init进程通过解析 init.rc 文件来启动的守护进程,涉及Android的启动流程,详情可以参考博文。lmkd 会创建名为 lmkd 的 socket,节点位于 /dev/socket/lmkd,该 socket 用于跟上层 framework 交互:
service lmkd /system/bin/lmkd
class core
group root readproc
critical
socket lmkd seqpacket 0660 system system
writepid /dev/cpuset/system-background/tasks
-
lmkd 启动后,循环等待ProcessList:
ProcessList
具体来看
- LMK_TARGET : 初始化 oom_adj,在 ActivityManagerService 中的applyOomAdjLocked() 方法中被调用
- LMK_PROCPRIO: 更新oom_adj,ActivityManagerService 会根据当前应用进程托管组件(即四大组件)生命周期的变化,及时的调用 applyOomAdjLocked(),更新进程状态及该状态对应的 oom_adj。其进程的状态可以参考博文安卓中的进程模型
- LMK_PROCREMOVE 移除进程(暂时无用)。在 ActivityManagerService 调用 updateOomAdjLocked() 时,会判断进程是否需要被杀死,若是,则调用 ProceeRecord::kill() 方法杀死该进程。
网友评论