17、进程与线程管理:adb shell ps、adb shell top、adb shell kill

说到 Android 调试,进程管理这块儿,我敢说每个开发都得打交道。你想想看,App 崩了、卡了、内存爆了,第一反应是什么?肯定是看看进程还在不在,CPU 是不是被谁吃光了。

今天咱们就聊聊三个最常用的命令:pstopkill。这三个命令,说白了就是进程管理的三板斧——查看、监控、干掉。

进程与线程管理核心命令 adb shell ps 查看进程列表 adb shell top 实时进程监控 adb shell kill 杀死进程 常用参数 • -A:显示所有进程 • -t:显示线程信息 • -p:指定PID • grep 过滤 常用参数 • -n:刷新次数 • -d:刷新间隔(秒) • -s:排序字段 • -m:最大显示数 信号类型 • -9 (SIGKILL):强制 • -15 (SIGTERM):正常 • -3 (SIGQUIT):dump • -2 (SIGINT):中断

17.1 adb shell ps:查看进程列表

ps 命令,全称 Process Status。我最早接触 Linux 时就在用这个命令。在 Android 上,它用来列出当前系统中所有正在运行的进程。

直接敲 adb shell ps,你会看到类似这样的输出:

USER      PID   PPID  VSIZE  RSS   WCHAN    PC         NAME
root      1     0     10568  928   SyS_epoll_ 0000000000 S /init
system    1234  1     23456  1234  SyS_epoll_ 0000000000 S system_server
u0_a123   5678  1234  45678  5678  SyS_epoll_ 0000000000 S com.example.myapp
shell     7890  1234  12345  2345  SyS_epoll_ 0000000000 S adbd

各列含义我简单说一下:

列名含义说明
USER进程所属用户系统进程通常是 root 或 system,App 进程是 u0_aXXX
PID进程ID每个进程的唯一标识,kill 的时候要用
PPID父进程ID谁生了你?比如 App 的父进程通常是 zygote
VSIZE虚拟内存大小(KB)进程申请的虚拟地址空间
RSS常驻内存大小(KB)实际占用的物理内存,这个更关键
NAME进程名可执行文件或包名
我的小习惯: 我经常用 adb shell ps | grep com.example 来快速定位某个 App 的进程。比如排查后台服务是否存活,一查便知。

17.2 进阶用法:查看线程信息

有时候光看进程不够,你还得看线程。比如某个 App 卡顿,可能是某个线程在搞鬼。

-t 参数可以显示线程:

adb shell ps -t | grep com.example.myapp

输出会多出 TID 列(线程ID),每个线程一行。我记得有一次线上反馈 App 启动慢,我用 ps -t 一看,发现有个线程在死循环,直接定位到了问题代码。

注意: 有些 Android 版本(尤其是高版本)对 ps 的参数支持有限。如果 -t 不好使,可以试试 adb shell ps -T 或者直接用 top -H

17.3 adb shell top:实时进程监控

ps 是静态快照,top 是动态监控。它会持续刷新,显示 CPU 和内存占用最高的进程。

基本用法:

adb shell top

你会看到类似这样的实时界面:

Tasks: 123 total, 1 running, 122 sleeping
Mem: 1844674k total, 1234567k used, 609107k free
Swap: 0k total, 0k used, 0k free

PID   PR   CPU%  S   #THR   VSS     RSS     NAME
1234  0    12%   S   45     23456K  1234K   system_server
5678  0    8%    S   12     45678K  5678K   com.example.myapp
7890  0    2%    S   3      12345K  2345K   adbd

关键列说明:

列名含义
CPU%CPU 使用率百分比
S进程状态(S=睡眠,R=运行,D=不可中断)
#THR线程数
VSS虚拟内存
RSS常驻内存
实用技巧:adb shell top -n 1 只刷新一次,适合脚本采集数据。用 adb shell top -d 2 设置刷新间隔为 2 秒。

17.4 排序与过滤

默认 top 按 CPU 排序。你可以用 -s 参数改排序字段:

# 按内存排序
adb shell top -s rss

# 按线程数排序
adb shell top -s thr

我个人最常用的是 adb shell top -m 10,只显示前 10 个进程,屏幕不花眼。

17.5 adb shell kill:杀死进程

发现某个进程不对劲,比如 CPU 飙到 100% 下不来,怎么办?直接干掉它。

基本语法:

adb shell kill [信号] PID

常用信号:

信号数字含义场景
SIGTERM15正常终止给进程一个善后的机会
SIGKILL9强制杀死进程无响应时使用
SIGINT2中断类似 Ctrl+C
SIGQUIT3退出并 dump生成 ANR 日志用

举个例子:

# 先找到进程
adb shell ps | grep myapp

# 正常杀死
adb shell kill 5678

# 强制杀死(如果正常杀不死)
adb shell kill -9 5678
我曾经踩过的坑: 有一次我直接 kill -9 了一个系统进程,结果手机直接重启了。所以,能正常杀就别用 -9,尤其是系统进程。App 进程倒是无所谓,Android 会帮你重启。

17.6 杀死所有相关进程

有时候一个 App 有多个进程,一个一个杀太麻烦。可以用 killall

adb shell killall com.example.myapp

不过要注意,killall 在某些 Android 版本上可能没有。这时候可以配合 psawk 写个组合命令:

adb shell "ps | grep com.example | awk '{print \$2}' | xargs kill"
小提示: 如果你只是想重启 App,其实不用 kill。用 adb shell am force-stop com.example.myapp 更优雅,系统会帮你清理资源再停止。

17.7 实战:定位 CPU 飙高问题

我分享一个真实案例。有一次测试反馈说某个页面滑动卡顿。我连上 adb,三步定位:

  1. adb shell top -m 5 -d 1 看 CPU 占用最高的进程
  2. 发现是 com.example.gallery 占 30% CPU
  3. adb shell ps -t | grep com.example.gallery 看线程,发现有个 ImageDecoder 线程一直在跑

最后定位到是图片解码没做缓存,每次滑动都重新解码。嗯,这就是进程和线程管理的价值——帮你快速找到问题根源。

17.8 总结一下

这三个命令,我几乎每天都会用到:

  • ps:看进程在不在,PID 是多少
  • top:看谁在吃 CPU/内存,实时监控
  • kill:发现问题,果断干掉

你想想看,没有这些命令,你就像蒙着眼睛在调试。有了它们,系统里每个进程都清清楚楚。下次遇到 App 卡顿或者内存泄漏,别急着拍脑袋,先连上 adb 看看进程再说。


公众号:蓝海资料掘金营,微信deep3321