17、进程与线程管理:adb shell ps、adb shell top、adb shell kill
说到 Android 调试,进程管理这块儿,我敢说每个开发都得打交道。你想想看,App 崩了、卡了、内存爆了,第一反应是什么?肯定是看看进程还在不在,CPU 是不是被谁吃光了。
今天咱们就聊聊三个最常用的命令:ps、top 和 kill。这三个命令,说白了就是进程管理的三板斧——查看、监控、干掉。
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 一看,发现有个线程在死循环,直接定位到了问题代码。
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
常用信号:
| 信号 | 数字 | 含义 | 场景 |
|---|---|---|---|
| SIGTERM | 15 | 正常终止 | 给进程一个善后的机会 |
| SIGKILL | 9 | 强制杀死 | 进程无响应时使用 |
| SIGINT | 2 | 中断 | 类似 Ctrl+C |
| SIGQUIT | 3 | 退出并 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 版本上可能没有。这时候可以配合 ps 和 awk 写个组合命令:
adb shell "ps | grep com.example | awk '{print \$2}' | xargs kill"
adb shell am force-stop com.example.myapp 更优雅,系统会帮你清理资源再停止。
17.7 实战:定位 CPU 飙高问题
我分享一个真实案例。有一次测试反馈说某个页面滑动卡顿。我连上 adb,三步定位:
adb shell top -m 5 -d 1看 CPU 占用最高的进程- 发现是
com.example.gallery占 30% CPU adb shell ps -t | grep com.example.gallery看线程,发现有个ImageDecoder线程一直在跑
最后定位到是图片解码没做缓存,每次滑动都重新解码。嗯,这就是进程和线程管理的价值——帮你快速找到问题根源。
17.8 总结一下
这三个命令,我几乎每天都会用到:
- ps:看进程在不在,PID 是多少
- top:看谁在吃 CPU/内存,实时监控
- kill:发现问题,果断干掉
你想想看,没有这些命令,你就像蒙着眼睛在调试。有了它们,系统里每个进程都清清楚楚。下次遇到 App 卡顿或者内存泄漏,别急着拍脑袋,先连上 adb 看看进程再说。
公众号:蓝海资料掘金营,微信deep3321