Watchdog
的中文的“看门狗”,有保护的意思。最先引入Watchdog是在单片机系统中,因为单片机的工做环境容易受到外界磁场的干扰,致使程序“跑飞”,形成整个系统没法正常工做,所以,引入了一个“看门狗”,对单片机的运行状态进行实时监测,针对运行故障作一些保护处理,譬如让系统重启。这种Watchdog属于硬件层面,必须有硬件电路的支持。java
Linux也引入了Watchdog,在Linux内核下,当Watchdog启动后,便设定了一个定时器,若是在超时时间内没有对/dev/Watchdog进行写操做,则会致使系统重启。经过定时器实现的Watchdog属于软件层面。android
Android设计了一个软件层面Watchdog,用于保护一些重要的系统服务,当出现故障时,一般会让Android系统重启。因为这种机制的存在,就常常会出现一些system_server进程被Watchdog杀掉而发生手机重启的问题。ide
本文指望回答如下问题:函数
- Watchdog是怎么工做的?这涉及到Watchdog的工做机制。
- 遇到Watchdog的问题该怎么办?这涉及到分析Watchdog问题的惯用方法。
咱们以frameworks/base/services/core/java/com/android/server/Watchdog.java为蓝本,分析Watchdog的实现逻辑。为了描述方便,ActivityManagerService, PackageManagerService, WindowManagerService会分别简称为AMS, PKMS, WMS。oop
Android的Watchdog是一个单例线程,在System Server时就会初始化Watchdog。Watchdog在初始化时,会构建不少HandlerChecker,大体能够分为两类:post
Monitor Checker,用于检查是Monitor对象可能发生的死锁, AMS, PKMS, WMS等核心的系统服务都是Monitor对象。ui
Looper Checker,用于检查线程的消息队列是否长时间处于工做状态。Watchdog自身的消息队列,Ui, Io, Display这些全局的消息队列都是被检查的对象。此外,一些重要的线程的消息队列,也会加入到Looper Checker中,譬如AMS, PKMS,这些是在对应的对象初始化时加入的。this
private Watchdog() { .... mMonitorChecker = new HandlerChecker(FgThread.getHandler(), "foreground thread", DEFAULT_TIMEOUT); mHandlerCheckers.add(mMonitorChecker); mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()), "main thread", DEFAULT_TIMEOUT)); mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(), "ui thread", DEFAULT_TIMEOUT)); mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(), "i/o thread", DEFAULT_TIMEOUT)); mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(), "display thread", DEFAULT_TIMEOUT)); ... }
两类HandlerChecker的侧重点不一样,Monitor Checker预警咱们不能长时间持有核心系统服务的对象锁,不然会阻塞不少函数的运行; Looper Checker预警咱们不能长时间的霸占消息队列,不然其余消息将得不处处理。这两类都会致使系统卡住(System Not Responding)。google
Watchdog初始化之后,就能够做为system_server进程中的一个单独的线程运行了。但这个时候,还不能触发Watchdog的运行,由于AMS, PKMS等系统服务尚未加入到Watchdog的监测集。 所谓监测集,就是须要Watchdog关注的对象,Android中有成千上万的消息队列在同时运行,然而,Watchdog毕竟是系统层面的东西,它只会关注一些核心的系统服务。lua
Watchdog提供两个方法,分别用于添加Monitor Checker对象和Looper Checker对象:
public void addMonitor(Monitor monitor) { // 将monitor对象添加到Monitor Checker中, // 在Watchdog初始化时,能够看到Monitor Checker自己也是一个HandlerChecker对象 mMonitors.add(monitor); } public void addThread(Handler thread, long timeoutMillis) { synchronized (this) { if (isAlive()) { throw new RuntimeException("Threads can't be added once the Watchdog is running"); } final String name = thread.getLooper().getThread().getName(); // 为Handler构建一个HandlerChecker对象,其实就是**Looper Checker** mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis)); } }
被Watchdog监测的对象,都须要将本身添加到Watchdog的监测集中。如下是AMS的类定义和构造器的代码片断:
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { public ActivityManagerService(Context systemContext) { ... Watchdog.getInstance().addMonitor(this); Watchdog.getInstance().addThread(mHandler); } public void monitor() { synchronized (this) { } } }
AMS实现了Watchdog.Monitor接口,这个接口只有一个方法,就是monitor(),它的做用后文会再解释。这里能够看到在AMS的构造器中,将本身添加到Monitor Checker对象中,而后将本身的handler添加到Looper Checker对象中。 其余重要的系统服务添加到Watchdog的代码逻辑都与AMS差很少。
整个Android系统中,被monitor的对象并很少,十个手指头就能数出来Watchdog.Monitor的实现类的个数。
Watchdog自己是一个线程,它的run()方法实现以下:
@Override public void run() { boolean waitedHalf = false; while (true) { ... synchronized (this) { ... // 1. 调度全部的HandlerChecker for (int i=0; i<mHandlerCheckers.size(); i++) { HandlerChecker hc = mHandlerCheckers.get(i); hc.scheduleCheckLocked(); } ... // 2. 开始按期检查 long start = SystemClock.uptimeMillis(); while (timeout > 0) { ... try { wait(timeout); } catch (InterruptedException e) { Log.wtf(TAG, e); } ... timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start); } // 3. 检查HandlerChecker的完成状态 final int waitState = evaluateCheckerCompletionLocked(); if (waitState == COMPLETED) { ... continue; } else if (waitState == WAITING) { ... continue; } else if (waitState == WAITED_HALF) { ... continue; } // 4. 存在超时的HandlerChecker blockedCheckers = getBlockedCheckersLocked(); subject = describeCheckersLocked(blockedCheckers); allowRestart = mAllowRestart; } ... // 5. 保存日志,判断是否须要杀掉系统进程 Slog.w(TAG, "*** GOODBYE!"); Process.killProcess(Process.myPid()); System.exit(10); } // end of while (true) }
以上代码片断主要的运行逻辑以下:
只要Watchdog没有发现超时的任务,HandlerChecker就会被不停的调度,那HandlerChecker具体作一些什么检查呢? 直接上代码:
public final class HandlerChecker implements Runnable { public void scheduleCheckLocked() { // Looper Checker中是不包含monitor对象的,判断消息队列是否处于空闲 if (mMonitors.size() == 0 && mHandler.getLooper().isIdling()) { mCompleted = true; return; } ... // 将Monitor Checker的对象置于消息队列以前,优先运行 mHandler.postAtFrontOfQueue(this); } @Override public void run() { // 依次调用Monitor对象的monitor()方法 for (int i = 0 ; i < size ; i++) { synchronized (Watchdog.this) { mCurrentMonitor = mMonitors.get(i); } mCurrentMonitor.monitor(); } ... } }
对于Looper Checker而言,会判断线程的消息队列是否处于空闲状态。 若是被监测的消息队列一直闲不下来,则说明可能已经阻塞等待了很长时间
对于Monitor Checker而言,会调用实现类的monitor方法,譬如上文中提到的AMS.monitor()方法, 方法实现通常很简单,就是获取当前类的对象锁,若是当前对象锁已经被持有,则monitor()会一直处于wait状态,直到超时,这种状况下,极可能是线程发生了死锁
至此,咱们已经分析了Watchdog的工做机制,回答了咱们提出的第一个问题:
Watchdog定时检查一些重要的系统服务,举报长时间阻塞的事件,甚至杀掉system_server进程,让Android系统重启。