WatchDog 工作原理

一、概述

Android系统中,有硬件WatchDog用于定时检测关键硬件是否正常工作,类似地,在framework层有一个软件WatchDog用于定期检测关键系统服务是否发生死锁事件。WatchDog功能主要是分析系统核心服务和重要线程是否处于Blocked状态。

  • 监视reboot广播;
  • 监视mMonitors关键系统服务是否死锁。

二、启动流程

2.1 startOtherServices

[-> SystemServer.java]

2.2 getInstance

[-> Watchdog.java]

2.2.1 创建Watchdog

[-> Watchdog.java]

Watchdog继承于Thread,创建的线程名为”watchdog”。mHandlerCheckers是记录着所有的HandlerChecker对象的列表。

Watchdog监控的线程有:

线程名 对应handler 含义
main thread new Handler(MainLooper) 当前主线程
android.fg FgThread.getHandler 前台线程
android.ui UiThread.getHandler UI线程
android.io IoThread.getHandler I/O线程
android.display DisplayThread.getHandler Display线程

DEFAULT_TIMEOUT默认为60s,调试时才为10s方便找出潜在的ANR问题。

2.2.2 HandlerChecker

[-> Watchdog.java]

mMonitors记录所有Watchdog目前正在监控的服务。

2.2.3 监控Binder线程

在小节【2.2.1】创建Watchdog时,通过addMonitor(new BinderThreadMonitor())来监控Binder线程, 这里拆分两步骤:

  • addMonitor
  • new BinderThreadMonitor
2.2.3.1 addMonitor

将monitor添加到HandlerChecker的成员变量mMonitors列表中。

2.2.3.2 BinderThreadMonitor

blockUntilThreadAvailable最终调用的是IPCThreadState,等待有空闲的binder线程

可见addMonitor(new BinderThreadMonitor())是将Binder线程添加到android.fg线程的handler(mMonitorChecker)来检查是否工作正常。

2.2.4 Monitor

能够被Watchdog监控的系统服务都实现了Watchdog.Monitor接口。 实现该接口类:

  • ActivityManagerService
  • PowerManagerService
  • WindowManagerService
  • InputManagerService
  • NetworkManagementService
  • MountService
  • NativeDaemonConnector
  • BinderThreadMonitor
  • MediaProjectionManagerService
  • MediaRouterService
  • MediaSessionService

2.3 init

[-> Watchdog.java]

2.3.1 RebootRequestReceiver

[-> Watchdog.java]

2.3.2 rebootSystem

[-> Watchdog.java]

最终是通过PowerManagerService来完成重启操作,具体的重启流程后续会单独讲述。

2.4 小节

获取watchdog实例对象,并注册reboot广播

  • mHandlerCheckers记录所有的HandlerChecker对象的列表,包括foreground, main, ui, i/o, display线程的handler;
  • mMonitors记录所有Watchdog目前正在监控Monitor,此处为BinderThreadMonitor;
  • 注册reboot广播,最终是通过PowerManagerService来完成;
  • 系统每间隔1分钟,执行一次monitor操作, 当系统hang时间超过1分钟则执行run()方法;

下面来看看当系统hang超过1分钟时,进入watchdog.run()的过程:

三、Watchdog

3.1 run

3.2 scheduleCheckLocked

postAtFrontOfQueue(this),该方法输入参数为Runnable对象,根据消息机制,回调HandlerChecker中的run方法。

3.2.1 HandlerChecker.run

回调的方法,例如BinderThreadMonitor.monitor

3.3 evaluateCheckerCompletionLocked

获取mHandlerCheckers列表中等待状态值最大的state.

3.3.1 getCompletionStateLocked

  • COMPLETED = 0:等待完成;
  • WAITING = 1:等待时间小于DEFAULT_TIMEOUT的一半,即30s;
  • WAITED_HALF = 2:等待时间处于30s~60s之间;
  • OVERDUE = 3:等待时间大于或等于60s。

3.4 AMS.dumpStackTraces

关于trace内容,这里就不细说,直接说说结论:

  1. 调用Process.sendSignal()向目标进程发送信号SIGNAL_QUIT;
  2. 分别调用backtrace.dump_backtrace(),输出/system/bin/mediaserver,/system/bin/sdcard,/system/bin/surfaceflinger这3个进程的backtrace;
  3. 统计CPU使用率;
  4. 调用Process.sendSignal()向其他进程发送信号SIGNAL_QUIT。

3.5 dumpKernelStackTraces

native_dumpKernelStacks调用到android_server_Watchdog.dumpKernelStacks

3.6 doSysRq

通过向节点/proc/sysrq-trigger写入字符,触发kernel来dump所有阻塞线程,输出所有CPU的backtrace到kernel log。

3.7 dropBox

关于dropbox已在dropBox源码篇详细讲解过,输出文件到/data/system/dropbox,比如system_app_crash。

3.8 killProcess

Process.killProcess已经在文章理解杀进程的实现原理已详细讲解,通过发送信号9给目标进程来完成杀进程的过程。

当杀死system_server进程,从而导致zygote进程自杀,进而触发init执行重启Zygote进程,这便出现了手机framework重启的现象。

四、小结

watchdog在check过程中出现阻塞1分钟的情况,则会输出:

  1. AMS.dumpStackTraces
    • kill -3
    • backtrace.dump_backtrace()
  2. dumpKernelStackTraces,输出kernel栈信息
  3. dropBox,输出文件到/data/system/dropbox

作者微博:@Gityuan

原文出处:Gityuan.com

1 2 收藏 评论

关于作者:gityuan

Android系统工程师,www.gityuan.com博主,个人新浪微博:http://weibo.com/gityuan 个人主页 · 我的文章 · 3 ·     

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部