AMS进程管理与优先级调度策略详解
ActivityManagerService(AMS)作为Android系统的核心服务之一,其进程管理和优先级调度机制对系统的性能和资源利用率起着决定性作用。以下从七个维度全面剖析AMS的进程管理体系:
1. 进程分类体系
AMS将应用进程划分为五类,每类对应于不同的生命周期状态和资源优先级:
进程类别 | 判定条件 | 典型oom_adj值 | 存活时间 |
前台进程 | 正在交互的Activity/bound Service/前台Service/执行onReceive的Broadcast | 0-1 | 最晚被kill |
可见进程 | 可见但非交互的Activity/bound Service | 2-7 | 较高 |
服务进程 | 通过startService启动且未绑定的后台Service | 8-15 | 中等 |
后台进程 | 含有已停止Activity(stop状态) | 被加入LRU列表 | 较短 |
空进程 | 无任何活跃组件(缓存进程) | 15+ | 最先被kill |
2. 调度优先级调整机制
AMS通过两组核心API实现动态优先级调控:
2.1 Linux原生优先级控制
// 设置进程nice值(-20~19)void setThreadPriority(int tid, int priority); // 设置调度策略(SCHED_NORMAL/SCHED_FIFO等)void setThreadScheduler(int tid, int policy);
典型场景:
- 前台Activity线程设置nice=-10
- RenderThread通常设置SCHED_FIFO策略
2.2 Android扩展控制(EAS)
// cgroup控制器路径/sys/fs/cgroup/cpu/foreground/tasks/sys/fs/cgroup/cpu/background/tasks// schedtune调控节点/dev/stune/top-app/tasks
权重分配:
- 前台进程获得**70%~80%**的CPU时间片
- 后台服务限制为5%~10%
3. OOM调整策略
AMS通过oom_adj与Linux的Low Memory Killer(LMK)协同工作:
// 关键adj值阈值static final int FOREGROUND_APP_ADJ = 0;static final int VISIBLE_APP_ADJ = 7;static final int SERVICE_ADJ = 15;// 计算方法int computeOomAdjLocked(ProcessRecord app) {if (app.thread == null) return BAD_APP_ADJ;if (app.instr != null) return FOREGROUND_APP_ADJ;...}
LMK触发逻辑:
@startumlstart:系统内存紧张;repeat:检查/proc/meminfo;-> mem_available < threshold;:kill oom_adj>=当前阈值的最小进程;repeat while (内存仍不足?) is (是)-> 否;stop@enduml
4. LRU管理算法
AMS维护双索引LRU列表实现精细化回收:
// 核心数据结构final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<>();// 两个关键分界点int mLruProcessActivityStart; // Activity进程起始点int mLruProcessServiceStart; // Service进程起始点
更新规则:
- 含Activity的进程插入到
mLruProcessActivityStart
之后 - 纯Service进程插入到
mLruProcessServiceStart
之后 - 空进程始终位于列表头部
5. 动态调整策略
AMS根据场景变化实时调整策略:
场景 | 优先级变化 | 触发条件 |
绑定前台Service | oom_adj从15→0 | bindService调用 |
Activity进入后台 | nice值从-10→5 | onStop回调完成 |
启动前台通知 | 加入schedtune/top-app分组 | startForegroundService调用 |
内存压力增大 | 后台进程adj+5 | mem_pressure事件触发 |
游戏模式激活 | 渲染线程升为RT优先级 | GameManagerService通知 |
6. 关键方法实现
6.1 updateLruProcessLocked
void updateLruProcessLocked(ProcessRecord app) {// 从LRU移除旧记录mLruProcesses.remove(app);// 计算新位置int index = computeLruIndex(app);mLruProcesses.add(index, app);// 更新边界索引if (hasActivities(app)) {mLruProcessActivityStart = index + 1;} else if (hasServices(app)) {mLruProcessServiceStart = index + 1;}}
6.2 updateOomAdjLocked
final void updateOomAdjLocked(ProcessRecord app) {// 计算新adj值int adj = computeOomAdjLocked(app);// 应用调整Process.setOomAdj(app.pid, adj);// 更新调度策略if (adj <= VISIBLE_APP_ADJ) {setThreadGroup(app.pid, THREAD_GROUP_TOP_APP);}}
7. 调试与性能分析
7.1 状态检查命令
# 查看进程adj值adb shell ps -A -o PID,ADJ,NAME# 获取LRU列表adb shell dumpsys activity lru
7.2 重要Trace标记
事件名, 触发阶段, 解析要点updateOomAdj, 优先级调整, adj值变化超过5需关注setPriority, 线程调度变更, 检查nice值合理性proc_died, 进程终止, 结合adj值分析被杀原因
AMS的进程管理是Android系统资源调控与用户体验平衡的艺术体现。其设计哲学可概括为:
- 两级防御:通过oom_adj控制内存回收优先级 + cgroup管理CPU资源分配
- 动态感知:实时响应Activity/ForegroundService等组件状态变化
- 渐进式降级:随着使用间隔拉长逐步降低资源配额
- 场景化策略:游戏/VR等特殊场景触发专用优化路径