Android framework--谈谈AMS.updateOomAdjLocked

关于Android系统的内存回收机制,相信大家都不陌生,Android基于各个应用进程承载四大组件的状态对应用进程进行重要性评估,并在系统内存紧张时根据重要性由低到高来选择杀死应用进程,以达到释放内存的目的。重要性评估由AMS执行,具体来说就是AMS.updateOomAdjLocked函数,反过来说,AMS.updateOomAdjLocked的作用就是更新应用进程的重要性。

应用进程(ProcessRecord)的重要性由三个状态值表示:

  • adj:LMK杀进程的评分依据
  • procState:指示进程状态
  • schedGroup:指示进程调度策略

本文不会分析该函数的具体执行,而是讨论这三个状态值之间的差异,代码参考Android N。


基本的思考

既然要评估进程的重要性,并以此作为LMK回收进程的依据,理论上来讲由单个状态来指示重要性,并告知LMK应该是最好的方案,简单粗暴,逻辑清晰。大家从很多地方都可以得知,oom_adj就是提供给LMK进行内存回收的依据,但是对于procState和schedGroup要么一笔带过,要么干脆不提及。但是既然存在这么两个东西,必然有其存在的意义。

我们先大概讲下AMS.updateOomAdjLocked的执行流程:

updateOomAdjLocked(ProcessRecord app)
    -updateOomAdjLocked(ProcessRecord app, int cachedAdj,
               ProcessRecord TOP_APP, boolean doingAll, long now) 
        -computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
            boolean doingAll, long now)
        -applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
            long nowElapsed)
updateOomAdjLocked()
    -computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
            boolean doingAll, long now)
        -applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
            long nowElapsed)

有上述两种执行路径,相同的空格缩进表示函数调用栈的同一级,注意updateOomAdjLocked有多个重载版本。重点说明出下面几点:

  • updateOomAdjLocked在应用进程的组件运行状态发生改变时被调用,比如有Service启动,有广播接收者收到广播,有Activity启动等,这很好理解,因为进程重要性的计算就依赖于组件运行状态,既然组件运行状态发生了改变,就应该实时更新;
  • computeOomAdjLocked根据一定规则计算出三个状态值,这个规则跟Android将进程划分的5个优先级有关系,即前台进程、可见进程、服务进程、后台进程、空进程,这里不详细说明;
  • applyOomAdjLocked将computeOomAdjLocked计算出的三个状态值应用起来,即真正发挥这三个状态值的作用。

既然要分析这三个状态值的作用,看源码如何使用这些值就是最好的办法,从上面可以知道,applyOomAdjLocked是我们的切入点。


applyOomAdjLocked

下面代码中涉及的ProcessRecord中cur开头的字段均为computeOomAdjLocked函数计算出的当前状态值,比如curAdj,curProcState,curSchedGroup,下面从代码的角度分别描述它们的作用。

adj

if (app.curAdj != app.setAdj) {
    ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj);
    if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
            "Set " + app.pid + " " + app.processName + " adj " + app.curAdj + ": "
            + app.adjType);
    app.setAdj = app.curAdj;
    app.verifiedAdj = ProcessList.INVALID_ADJ;
}

curAdj是computeOomAdjLocked计算出的adj值,赋值给setAdj,并且调用ProcessList.setOomAdj,继续往下看:

public static final void setOomAdj(int pid, int uid, int amt) {
    if (amt == UNKNOWN_ADJ)
        return;

    long start = SystemClock.elapsedRealtime();
    ByteBuffer buf = ByteBuffer.allocate(4 * 
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值