进程列表获取与筛选

现象识别

当设备出现以下现象时,需要第一时间获取进程列表:

  • 耗电异常:待机状态电池曲线陡降,系统 Top 耗电排行中“Android 系统”或“媒体服务器”占比过高
  • 设备发热:未运行大型游戏时机身持续高温,CPU 占用率长期 > 50%
  • 界面卡顿 / ANR:应用无响应提示频繁出现,或触控延迟明显
  • 后台自启 / 相互唤醒:某应用被强杀后自动复活,或全家桶链式启动
  • 隐私/安全怀疑:发现陌生包名、高权限进程或子进程异常
排查切入点:先通过系统设置 → 开发者选项 → 正在运行的服务 做初步列表,再使用 adb shell 命令精确采集。

数据采集

核心命令包括 ps 和 top,以及辅助的 pidof、pgrep。采集时需关注进程名、PID、UID、内存和 CPU 占用。

1. ps 命令

列出当前所有进程的瞬间快照,命令格式及常用参数:

adb shell ps                    # 默认 SYSVR4 风格(USER PID PPID … NAME)
adb shell ps -A                # 显示所有进程(Android 7+)
adb shell ps -T               # 显示线程(轻量级进程)
adb shell ps -eo pid,ppid,uid,cpu,args --sort=-%cpu  # Linux 原生格式,按 CPU 降序

输出列含义:

列含义
USER运行该进程的 UID 名称(如 u0_a15)
PID进程唯一 ID
PPID父进程 ID
CPU瞬间 CPU 占用百分比(仅部分格式)
NAME / COMMAND进程名或可执行文件路径

2. top 命令

动态刷新进程资源占用,适合定位瞬时高负载进程:

adb shell top -n 1 -b           # 单次批处理输出(非交互)
adb shell top -d 2 -n 5         # 每 2 秒采样一次,共 5 次
adb shell top -o -%CPU          # 按 CPU 占用排序(按需调整参数)

常见输出字段:PID、PR、CPU%、S(状态)、VIRT、RES、NAME。

3. 通过包名查询 PID

adb shell pidof com.example.app        # 直接返回 PID
adb shell ps | grep com.example.app    # 字符串匹配

4. 通过 UID 筛选

先获取应用 UID:

adb shell dumpsys package com.example.app | grep userId=
adb shell pm list packages -U | grep com.example.app

然后用 UID 过滤进程:

adb shell ps | grep u0_a15              # u0_a15 是举例 UID
注意:不同 Android 版本的 ps 输出格式有差异(SYSVR4 / BSD / Linux raw)。建议统一使用 ps -A -o PID,UID,CPU,ARGS(Linux 原生格式)以获得稳定列顺序。

原因定位

通过采集的进程列表,使用以下排查表判断异常进程:

异常特征可疑指标常见原因
CPU 占用持续 > 40%top 中 %CPU 列长期高居不下应用死循环、渲染过重、恶意挖矿
内存占用异常大VIRT 或 RES 远超同类应用内存泄漏、数据库缓存巨大、Bitmap 未释放
进程名与包名不符ps 显示 system_server 但包名是第三方进程注入、伪装系统进程
父进程为 Zygote 但 UID 异常PPID=1 但 USER=root 且未授权Root 提权或恶意应用
进程数量成倍增长同一包名下出现多个 PID多进程架构失控、相互唤醒循环
无界面进程长期存活UID=u0_xxx 但无前台 Activity定时任务、常驻 Service、推送保活

故障树判断逻辑:

1. 是否系统进程(UID root/system/radio)?
   ├─是 → 检查 kernel 或 hal 层,关注 watchdog、surfaceflinger、audioserver
   └─否 → 进入第 2 步
2. 该进程是否与前台应用相关?
   ├─是 → 检查该应用自身的 Activity 生命周期、Service 泄漏
   └─否 → 进入第 3 步
3. 该进程是否存在频繁唤醒锁(wake lock)?
   ├─是 → 检查 PowerManager.WakeLock 泄漏或第三方 SDK 保活
   └─否 → 进入第 4 步
4. 进程名是否包含 ams、system、input 等系统关键词?
   ├─是 → 可能系统服务异常,收集 anr trace / bugreport
   └─否 → 标记为可疑后台进程,采集完整堆栈

修复动作

  • 强制停止:adb shell am force-stop <package_name>
  • 杀死指定 PID:adb shell kill -9 <PID>(注意 system 级进程谨慎操作)
  • 卸载异常应用:adb uninstall <package_name>
  • 清除应用数据:adb shell pm clear <package_name>
  • 重启系统服务:针对 system_server 等异常,可尝试 adb shell am restart(部分设备支持)或直接 reboot
极端情况处理:若进程无法 kill(如 init 进程或 mediaserver),需要 adb root 后 adb shell stop 或 adb shell setprop ctl.stop <service_name>,再重新启动。

复测

  1. 再次执行 adb shell top -n 1 -b | grep <package> 确认进程已被清除
  2. 观察 10 分钟:adb shell top -d 10 -n 6 -b > /tmp/cpu_log.txt 检查是否复活
  3. 检查关联进程:adb shell ps -A | grep <package> 确保全家桶未拉起
  4. 验证功能:启动目标应用,确认正常使用且无异常后台行为

预防

预防措施操作/命令
监控 CPU/内存基线使用 adb shell dumpsys cpuinfo 定期采样;脚本告警
限制后台运行开发者选项 → 后台进程限制 / 按需选择“不允许”
审查第三方 SDK 保活行为反复抓取 ps + top 对比前后关联进程链
使用 JobScheduler 代替 Service代码审计,确保长运行 Service 改为 JobScheduler 或 WorkManager
定期扫描异常 UID编写脚本:ps -A | awk '$2!="0" && $1!="root" && $1!="system" && $1!="radio" {print}'
进程排查流程图(第3章) 现象触发 耗电/发热/卡顿/ANR 数据采集 ps / top / pidof PID/UID 分析 识别进程归属 异常特征判断 CPU↑ 内存↑ 名不符 原因定位 故障树/排查表 修复动作 kill/force-stop/卸载 关键判断规则 UID vs PID 进程名含可疑字符 CPU/内存基线对比