其他
systemserver进程监控者--watchdog
The following article is from 牛晓伟 Author 牛晓伟
本文同样采用自述的方式来介绍systemserver进程的监控者watchdog,通过本文您将了解watchdog的作用,它是如何工作的。(文中代码基于Android13)
接下来看下我是如何启动的吧。
//SystemServer类
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
//Watchdog是单例,因此调用getInstance方法获取它的实例,该方法在下面
final Watchdog watchdog = Watchdog.getInstance();
//调用它的start方法,该方法在下面
watchdog.start();
省略代码······
watchdog.init(mSystemContext, mActivityManagerService);
省略代码······
}
//Watchdog类
public static Watchdog getInstance() {
if (sWatchdog == null) {
sWatchdog = new Watchdog();
}
return sWatchdog;
}
//私有构造方法
private Watchdog() {
//new 一个线程
mThread = new Thread(this::run, "watchdog");
省略代码······
}
//start方法
public void start() {
//调用线程的start方法
mThread.start();
}
结合上面的图文用文字来总结下我的工作原理:
遍历所有的 HandlerChecker,并依次执行每个 HandlerChecker 的 scheduleCheckLocked 方法。 等待 timeout 时间后 检查所有的 HandlerChecker 的状态 (它们的状态有 COMPLETED、WAITING、WAITED_HALF、OVERDUE四种)。 3.1 若没有 OVERDUE 状态的 HandlerChecker 则会继续从第 1 步开始重新执行。 3.2 若有 OVERDUE 状态的 HandlerChecker,则会进行超时处理,比如收集日志,杀掉systemserver进程。
3.1 HandlerChecker是啥?
3.1.1 HandlerChecker 的关键属性
3.1.2 HandlerChecker 的关键方法
3.1.3 HandlerChecker 如何监控
先把 mComplete 置为 false,再调用 mHander 的 postAtFrontOfQueue 方法,参数为当前 HandlerChecker 对象 (postAtFrontOfQueue 方法会把 Message 放入 Handler 对应的 MessageQueue 的最前面,保证它会被优先执行)。 如果 run 方法被顺利执行,会遍历 mMonitors,并且执行每个 Monitor 的 monitor 方法,若所有的 Monitor都被顺利执行,则会把 mComplete 置为 true 代表执行完毕,不存在耗时方法和死锁情况。
HandlerChecker 对应的 run 方法没有被执行,主要是因为 mHander 对应的 Looper 中正在被执行的 Message 确实出现了耗时情况。 mMonitors 中有些 Monitor 的 monitor 方法出现了超时情况。
3.1.4 添加被监控的 Handler
//Watchdog 类的构造方法
private Watchdog() {
省略代码······
//它主要用来监控各种锁
mMonitorChecker = new HandlerChecker(FgThread.getHandler(),
"foreground thread");
mHandlerCheckers.add(withDefaultTimeout(mMonitorChecker));
//监控systemserver的主线程的Handler
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(new Handler(Looper.getMainLooper()), "main thread")));
//UiThread主要用来显示UI,监控它的 Handler
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(UiThread.getHandler(), "ui thread")));
//IoThread主要用来io操作,监控它的Handler
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(IoThread.getHandler(), "i/o thread")));
//DisplayThread主要与显示有关
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(DisplayThread.getHandler(), "display thread")));
// AnimationThread动画相关
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(AnimationThread.getHandler(), "animation thread")));
省略代码······
}
3.1.5 添加被监控的锁
//ActivityManagerService类,它实现了Watchdog.Monitor接口
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback, ActivityManagerGlobalLock {
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
省略代码······
Watchdog.getInstance().addMonitor(this);
省略代码······
}
public void monitor() {
//获取到锁后,不执行任何代码,立即释放锁;若获取不到锁会一直阻塞
synchronized (this) { }
}
}
3.1.6 小结
3.2 再来看 scheduleCheckLocked 方法
//Watchdog类
public void scheduleCheckLocked(long handlerCheckerTimeoutMillis) {
//超时时间
mWaitMax = handlerCheckerTimeoutMillis;
//为true,则把mMonitorQueue添加到mMonitors
if (mCompleted) {
mMonitors.addAll(mMonitorQueue);
mMonitorQueue.clear();
}
//mPauseCount 大于0 说明需要暂停
if ((mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling())
|| (mPauseCount > 0)) {
//暂停则把 mCompleted 置为true
mCompleted = true;
return;
}
//还在运行,则直接返回
if (!mCompleted) {
// we already have a check in flight, so no need
return;
}
//重置各种信息
mCompleted = false;
mCurrentMonitor = null;
mStartTime = SystemClock.uptimeMillis();
//放入MessageQueue的最前面,保证被优先执行
mHandler.postAtFrontOfQueue(this);
}
3.3 检查所有的 HandlerChecker 状态
每个 HandlerChecker 都会根据自己的执行状态和执行时间返回自己的状态值,状态值有 COMPLETED、WAITING、WAITED_HALF、OVERDUE 四种,它们都是整数类型的,它们的值是从小到大,也就是 COMPLETED < WAITING < WAITED_HALF < OVERDUE,为啥要设置这几个状态值呢?
若是 WAITED_HALF,则代表该 HandlerChecker 已经执行了多余 timeout 一半的时间,该 HandlerChecker 有可能会出现超时,因此这时候会收集日志,不会跳出循环。 若是 OVERDUE,则有 HandlerChecker 出现了超时,则会进行超时处理,跳出循环。 若是 COMPLETED 和 WAITING,则会重新执行,不会跳出循环。
3.4 超时处理
收集日志。 把超时的 HandlerChecker 的堆栈信息收集起来。 杀掉SystemServer进程。
zygote进程检测到systemserver进程死掉的话也会“自杀”,init进程会重新启动zygote进程,zygote进程会启动systemserver进程,进而启动launcher。
最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!