Android稳定性系列6 WatchDog原理

一 概述

Watchdog 中文翻译是“看门狗”,有保护,监控的意思。最早引入 Watchdog 是在单片机系统中,由于单片机的工作环境容易受到外界磁场的干扰,导致程序“跑飞”,造成整个系统无法正常工作,因此,引入了一个“看门狗”,对单片机的运行状态进行实时监测,针对运行故障做一些保护处理,譬如让系统重启。这种 Watchdog 属于硬件层面,必须有硬件电路的支持。

Linux 也引入了 Watchdog,在 Linux 内核下,当 Watchdog 启动后,便设定了一个定时器,如果在超时时间内没有对 /dev/Watchdog 进行写操作,则会导致系统重启。通过定时器实现的 Watchdog 属于软件层面。

Android 在 framework 层设计了一个软件层面的 Watchdog,用于定期检测一些重要的系统服务,当出现故障(系统核心服务和重要线程处于 Blocked 状态)时,通常会让 Android 系统重启。由于这种机制的存在,就经常会出现 system_server 进程被 Watchdog 杀掉而发生手机重启的问题。

watchdog 的源码很简单,主要有以下两个功能:

  • 监控 system_server 中几个关键的锁,原理是在 android_fg 线程中尝试加锁
  • 监控几个常用线程的执行时间,原理是在这几个线程中执行任务

二 WatchDog初始化

2.1 startBootstrapServices

SystemServer.java

private void startBootstrapServices() {
   
   
    ......
    //创建watchdog
    final Watchdog watchdog = Watchdog.getInstance();    
    watchdog.start();
    ......
    //待AMS启动后注册reboot广播
    watchdog.init(mSystemContext, mActivityManagerService);
    ......
}

system_server 进程在启动的过程中初始化 WatchDog,主要有:

  • 创建 watchdog 对象,该对象本身继承于 Thread
  • 调用 start() 开始工作
  • 注册 reboot 广播

2.2 Watchdog.getInstance

Watchdog.java

public static Watchdog getInstance() {
   
   
    if (sWatchdog == null) {
   
   
        sWatchdog = new Watchdog();//单例模式,创建实例对象
    }
    return sWatchdog;
}

2.3 创建Watchdog

Watchdog.java

public class Watchdog extends Thread {
   
   
    //所有的HandlerChecker对象组成的列表
    //This handler will be used to post message back onto the main thread
    final ArrayList<HandlerChecker> mHandlerCheckers = new ArrayList<>();
    ......

    private Watchdog() {
   
   
        super("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));
        //将ui线程加入队列
        mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(),
                "ui thread", DEFAULT_TIMEOUT));
        //将i/o线程加入队列
        mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),
                "i/o thread", DEFAULT_TIMEOUT));
        //将display线程加入队列
        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));
        //Initialize monitor for Binder threads
        addMonitor(new BinderThreadMonitor());
        mOpenFdMonitor = OpenFdMonitor.create();
        // See the notes on DEFAULT_TIMEOUT.
        assert DB ||
                DEFAULT_TIMEOUT > 
                ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS;
    }
    ......
}

Watchdog 是一个单例线程,继承于 Thread,创建的线程名为 ”watchdog”。在 SystemServer 启动过程中初始化 Watchdog。Watchdog 在初始化时,会构建很多 HandlerChecker,大致可以分为两类:

  • Monitor Checker,用于检查 Monitor 对象可能发生的死锁,AMS,IMS,WMS PMS 等核心的系统服务都是 Monitor 对象
  • Looper Checker,用于检查线程的消息队列是否长时间处于工作状态。Watchdog 自身的消息队列,ui,io, Display 这些全局的消息队列都是被检查的对象。此外,一些重要的线程的消息队列,也会加入到 Looper Checker中,譬如 AMS,WMS 这些是在对应的对象初始化时加入的

两类 HandlerChecker 的侧重点不同,Monitor Checker 预警我们不能长时间持有核心系统服务的对象锁,否则会阻塞很多函数的运行;Looper Checker 预警我们不能长时间的霸占消息队列,否则其他消息将得不到处理。这两类都会导致系统卡住 (System Not Responding)。

2.3.1 Watchdog.HandlerChecker

public final class HandlerChecker implements Runnable {
   
   
        private final Handler mHandler;//Handler对象
        private final String mName;//线程描述名
        private final long mWaitMax;//最长等待时间
        //记录着监控的服务
        private final ArrayList<Monitor> mMonitors =
            new ArrayList<Monitor>();
        //添加监控服务队列
        private final ArrayList<Monitor> mMonitorQueue =
        new ArrayList<Monitor>();
        private boolean mCompleted;//开始检查时先设置成false
        private Monitor mCurrentMonitor;
        private long mStartTime;//开始准备检查的时间点
        private int mPauseCount;

        HandlerChecker(Handler handler, String name, long waitMaxMillis) {
   
   
            mHandler = handler;
            mName = name;
            mWaitMax = waitMaxMillis;
            mCompleted = true;
        }

        void addMonitorLocked(Monitor monitor) {
   
   
            mMonitorQueue.add(monitor);
        }

        public void scheduleCheckLocked() {
   
   
            if (mCompleted) {
   
   
                mMonitors.addAll(mMonitorQueue);
                mMonitorQueue
Android系统中的Watchdog机制是一种用于监控系统关键服务和线程是否正常运行的软件实现。其主要功能是检测SystemServer中各核心服务是否发生死锁或长时间阻塞,以确保系统的稳定性和可用性。 ### Watchdog的初始化 在SystemServer启动过程中,会创建并初始化Watchdog实例。通过调用`Watchdog.getInstance()`方法获取单例模式下的Watchdog对象[^2]。该对象随后被用来注册上下文环境以及与ActivityManagerService相关联,从而开始对系统服务进行监控。 ```java final Watchdog watchdog = Watchdog.getInstance(); watchdog.init(context, mActivityManagerService); ``` ### 工作原理 Watchdog作为一个独立运行的线程,在Android框架层定期检查关键系统服务的状态。它主要关注的是那些对于用户体验至关重要的服务,例如ActivityManagerService、WindowManagerService等。当这些服务中的任何一个处于Blocked状态超过预设的时间阈值(默认为30秒),Watchdog将触发一个诊断过程,并尝试恢复服务的正常运作。 - 如果服务在指定时间内未能恢复正常,则会执行进一步的操作,比如转储当前堆栈信息以便于后续分析。 - 若问题依旧存在且持续超过另一个更长的超时时间(通常是60秒),则可能采取重启SystemServer的方式来保障整个系统的可用性[^4]。 ### 监控内容 Watchdog不仅限于监视硬件层面的问题,它同样负责软件层面的关键任务监测。这包括但不限于: - 检测系统核心服务是否出现死锁事件。 - 分析重要线程是否长时间处于阻塞状态。 这种监控机制有助于及时发现潜在故障点,并通过日志记录提供详细的错误上下文信息,如logcat中显示的类似“*** WATCHDOG KILLING SYSTEM PROCESS...”的消息,帮助开发者快速定位问题所在[^4]。 ### 实现细节 为了实现上述功能,Watchdog内部维护了一组需要被监控的服务列表。每当一次完整的监控周期结束时,它会对列表中的每个服务进行健康状况评估。如果某个服务未能按时响应或者表现出异常行为,则根据配置策略采取相应措施。 此外,除了基本的心跳检测外,还可以设置特定条件下的回调函数来处理不同类型的异常情况。这种方式使得Watchdog能够灵活适应多种应用场景下的需求变化。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值