栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Watchdog机制原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Watchdog机制原理

Watchdog机制 1.什么是SWT:

Softwere Watchdog Timeout,顾名思义就是软件超时监控狗。

Watchdog.java 位于frameworks/base/services/core/java/com/android/server/Watchdog.java

2.为什么需要SWT:

System Server 进程是Android的一个核心进程,里面为App运行提供了很多核心服务,如AMS、WMS、PKMS等等,如果这些核心的服务和重要的线程卡住,就会导致相应的功能异常。如果没有一种机制让这些服务复位的话,就会严重影响用户的体验,所以Google引入了System Server Watchdog 机制,用来监控这些核心服务和重要线程是否被卡住。

3.原理框架示意图:

4.Watchdog的初始化:

Watchdog的初始化是在SystemServer init的后期,如果SystemServer在init的过程中卡死了,那么就意味着Watchdog不会生效。

Watchdog是一个单例线程,在SystemServer启动时就会获取它并初始化和启动(init/start).

  private void startOtherServices() {
      ...
          traceBeginAndSlog("InitWatchdog");
      final Watchdog watchdog = Watchdog.getInstance();
      watchdog.init(context, mActivityManagerService);
      traceEnd();
      ...
          traceBeginAndSlog("StartWatchdog");
      Watchdog.getInstance().start();
      traceEnd();
      ...
  }

Watchdog在初始化的时候会构建很多的HandlerChecker

private Watchdog() {
	super("watchdog");
    // Initialize handler checkers for each common thread we want to check.  Note
    // that we are not currently checking the background thread, since it can
    // potentially hold longer running operations with no guarantees about the timeliness
    // of operations there.
    // The shared foreground thread is the main checker.  It is where we
    // will also dispatch monitor checks and do other work.
    mMonitorChecker = new HandlerChecker(FgThread.getHandler(),
                   "foreground thread", DEFAULT_TIMEOUT);
    mHandlerCheckers.add(mMonitorChecker);
    // Add checker for main thread.  We only do a quick check since there
    // can be UI running on the thread.
    mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()),
                   "main thread", DEFAULT_TIMEOUT));
    // Add checker for shared UI thread.
    mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(),"ui thread", DEFAULT_TIMEOUT));
	// And also check IO thread.
 	mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),"i/o thread", DEFAULT_TIMEOUT));
    // And the display thread.
    mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
                                            "display thread", DEFAULT_TIMEOUT));
    // And the animation thread.
    mHandlerCheckers.add(new HandlerChecker(AnimationThread.getHandler(),
                                            "animation thread", DEFAULT_TIMEOUT));
    // And the surface animation thread.
    mHandlerCheckers.add(new HandlerChecker(SurfaceAnimationThread.getHandler(),
                                            "surface animation thread", DEFAULT_TIMEOUT));
	......
}
5.HandlerChecker分类:

大致可以分为两类

Montor Checker:用于检查Monitor对象是否发生死锁,AMP、PKMS、WMS等核心系统服务都是Monitor对象。所有需要被监控的Service都去实现了Watchdog的Monitor接口,该接口中只有一个方法 monitor()

与之对应的是addMonitor()方法,将Service放到mHandlerChecker的mMonitors列表中,该列表会不断调用Monitor.monitor()方法,这个方法的实现也比较简单,就是去获取对应的锁,如果获取到了就OK,如果线程死锁或者其它原因阻塞那么必然获取不到,monitor()方法也必然阻塞。

WindowManagerService.java 
    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
    @Override
    public void monitor() {
    synchronized (mWindowMap) { }
}

Lopper Checker,用于检查线程的消息队列是否长时间处于非空闲状态,Watchdog自身的消息队列,Ui, Io, Display这些全局的消息队列都是被检查的对象。此外,一些重要的线程的消息队列,也会加入到Looper Checker中,譬如AMS, PKMS,这些是在对应的对象初始化时加入的。

与之对应的方法是addThread(),将PowerManagerService、PackageManagerService、ActivityManagerService等几个主线程Handler保存到Watchdog.mHandlerCheckers列表中;同时还会把上面提到的mMonitorChecker也保存到Watchdog.mHandlerCheckers中;另外还会将foreground thread、ui thread、i/o thread 、display thread 、main thread的Handler也保存到Watchdog.mHandlerCheckers中来;

Watchdog会不断判断这些线程的Lopper是否空闲,如果是,那么必然就被阻塞了。

6.Watchdog的运作:

Watchdog本身是一个线程,它的run()方法实现如下:

@Override
public void run() {
    boolean waitedHalf = false; //标识第一个30s超时
    boolean mSFHang = false; //标识surfaceflinger是否hang
    while (true) {
        ...
        synchronized (this) {
            ...
            // 1. 调度所有的HandlerChecker
            for (int i=0; i 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();
            //超了60秒,此时便出问题了,收集超时的HandlerChecker
            subject = describeCheckersLocked(blockedCheckers);
            allowRestart = mAllowRestart;
        }
        ...
        // 5. 保存日志,判断是否需要杀掉系统进程
        Slog.w(TAG, "*** GOODBYE!");
        Process.killProcess(Process.myPid());
        System.exit(10);
    } // end of while (true)
    ......
}

以上代码片段主要的运行逻辑如下:

    Watchdog运行后,便开始无限循环,依次调用每一个HandlerChecker的scheduleCheckLocked()方法调度完HandlerChecker之后,便开始定期检查是否超时,每一次检查的间隔时间由CHECK_INTERVAL常量设定,为30秒每一次检查都会调用evaluateCheckerCompletionLocked()方法来评估一下HandlerChecker的完成状态:

    COMPLETED表示已经完成WAITING和WAITED_HALF表示还在等待,但未超时OVERDUE表示已经超时。默认情况下,timeout是1分钟,但监测对象可以通过传参自行设定,譬如PKMS的Handler Checker的超时是10分钟 如果超时时间到了,还有HandlerChecker处于未完成的状态(OVERDUE),则通过getBlockedCheckersLocked()方法,获取阻塞的HandlerChecker,生成一些描述信息保存日志,包括一些运行时的堆栈信息,这些日志是我们解决Watchdog问题的重要依据。如果判断需要杀掉system_server进程,则给当前进程(system_server)发送signal 9

只要Watchdog没有发现超时任务,HandlerChecker就会被不停的调度。

7.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();
        }
        ...
    }
}
8.小结:

对于Looper Checker而言,会判断线程的消息队列是否处于空闲状态。 如果被监测的消息队列一直闲不下来,则说明可能已经阻塞等待了很长时间。对于Monitor Checker而言,会调用实现类的monitor方法,比如上文中提到的AMS.monitor()方法, 方法实现一般很简单,就是获取当前类的对象锁,如果当前对象锁已经被持有,则monitor()会一直处于wait状态,直到超时,这种情况下,很可能是线程发生了死锁。

这基本就是Watchdog的监控原理,就先梳理这么多吧,后续的SWT/ANR问题的分析流程等遇到了再说吧。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/769583.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号