Android软Watchdog源码分析

http://blog.csdn.net/yangwen123/article/details/11264461

目录(?)[+]

Android系统中,所有的系统服务都运行在SystemServer进程中,如果实时监测系统所有服务是否正常运行呢?Android软 Watchdog就是用来胜任这个工作的,WatchDog的作用:

1).接收系统内部reboot请求,重启系统。

2).监护SystemServer进程,防止系统死锁。

Android watchdog类图:

Watchdog本身继承Thread,是一个线程类,监控任务运行在独立的线程中,但是Watchdog线程并没有自己的消息队列,该线程共用SystemServer主线程的消息队列。Watchdog有一个mMonitors成员变量,该变量是一个monitor类型的动态数组,用于保存所有Watchdog监测对象。Monitor定义为接口类型,需要加入Watchdog监控的服务必须实现Monitor接口。HeartbeatHandler类为WatchDog的核心,负责对各个监护对象进行监护。

Watchdog启动


WatchDog是在SystemServer进程中被初始化和启动的。在SystemServer 被Start时,各种Android服务被注册和启动,其中也包括了WatchDog的初始化和启动。
[java]  view plain  copy
  1. Slog.i(TAG, "Init Watchdog");  
  2. Watchdog.getInstance().init(context, battery, power, alarm,ActivityManagerService.self());  
  3. Watchdog.getInstance().start();  
Watchdog采用单例模式构造对象
[java]  view plain  copy
  1. public static Watchdog getInstance() {  
  2.     if (sWatchdog == null) {  
  3.         sWatchdog = new Watchdog();  
  4.     }  
  5.     return sWatchdog;  
  6. }  
Watchdog构造过程
[java]  view plain  copy
  1. private Watchdog() {  
  2.     super("watchdog");  
  3.     mHandler = new HeartbeatHandler();  
  4. }  
在构造Watchdog时创建了一个心跳HeartbeatHandler,用于处理Watchdog线程发送的MONITOR消息。接着调用Watchdog的init函数来初始化Watchdog对象:
[java]  view plain  copy
  1. public void init(Context context, BatteryService battery,  
  2.         PowerManagerService power, AlarmManagerService alarm,  
  3.         ActivityManagerService activity) {  
  4.     mResolver = context.getContentResolver();  
  5.     mBattery = battery;  
  6.     mPower = power;  
  7.     mAlarm = alarm;  
  8.     mActivity = activity;  
  9.     //注册重启广播接收器  
  10.     context.registerReceiver(new RebootReceiver(),new IntentFilter(REBOOT_ACTION));  
  11.     mRebootIntent = PendingIntent.getBroadcast(context,0new Intent(REBOOT_ACTION), 0);  
  12.     //注册重启请求广播接收器  
  13.     context.registerReceiver(new RebootRequestReceiver(),  
  14.             new IntentFilter(Intent.ACTION_REBOOT),  
  15.             android.Manifest.permission.REBOOT, null);  
  16.     mBootTime = System.currentTimeMillis();  
  17. }  
RebootReceiver负责接收由AlarManagerService发出的PendingIntent,并进行系统重启。
RebootRequestReceiver负责接收系统内部发出的重启Intent消息,并进行系统重启。

添加监控对象


在启动Watchdog前,需要向其添加监测对象。在Android4.1中有7个服务实现了Watchdog.Monitor接口,即这些服务都可以被Watchdog监控。
ActivityManagerService
InputManagerService
MountService
NativeDaemonConnector
NetworkManagementService
PowerManagerService
WindowManagerService

Watchdog提供了addMonitor方法来添加监控对象
[java]  view plain  copy
  1. public void addMonitor(Monitor monitor) {  
  2.     synchronized (this) {  
  3.         if (isAlive()) {  
  4.             throw new RuntimeException("Monitors can't be added while the Watchdog is running");  
  5.         }  
  6.         mMonitors.add(monitor);  
  7.     }  
  8. }  
添加过程只是将需要被Watchdog监控的对象添加到Watchdog的动态monitor数组mMonitors中。

Watchdog监控过程


当调用Watchdog.getInstance().start()将启动Watchdog线程,Watchdog执行过程如下:
[java]  view plain  copy
  1. public void run() {  
  2.     boolean waitedHalf = false;  
  3.     while (true) {  
  4.         /** 
  5.          * 反复设置mCompleted变量为false 
  6.          */  
  7.         mCompleted = false;   
  8.         /** 
  9.          * 发送一个MONITOR消息给心跳HeartbeatHandler处理,处理过程就是调用各个监控对象的monitor函数, 
  10.          * 如果各个被监控服务的monitor都顺利返回,心跳HeartbeatHandler会将mCompleted设置为true 
  11.          */  
  12.         if (mHandler.sendEmptyMessage(MONITOR)) {  
  13.             if (WATCHDOG_DEBUG) Slog.v(TAG,"**** -1-Watchdog MSG SENT! ****");  
  14.         }  
  15.         /** 
  16.          * Watchdog线程和SystemServer主线程共用同一个消息队列,为了在两个线程中改变mCompleted的值,这里必须使用线程同步机制 
  17.          */  
  18.         synchronized (this) {         
  19.             /** 
  20.              * TIME_TO_WAIT的默认时间为30s。此为第一次等待时间,WatchDog判断对象是否死锁的最长处理时间为1Min。 
  21.              */  
  22.             long timeout = TIME_TO_WAIT;  
  23.             /** 
  24.              * 获取当前时间 
  25.              */  
  26.             long start = SystemClock.uptimeMillis();  
  27.             /** 
  28.              * 等待30秒,等待HeartbeatHandler的处理结果。然后才会进行下一步动作。 
  29.              */  
  30.             while (timeout > 0 && !mForceKillSystem) {  
  31.                 try {  
  32.                     wait(timeout);  // notifyAll() is called when mForceKillSystem is set  
  33.                 } catch (InterruptedException e) {  
  34.                     Log.wtf(TAG, e);  
  35.                 }  
  36.                 timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);  
  37.             }  
  38.             /** 
  39.              * 如果所有监控对象在30s内能够顺利返回,则会得到mCompleted = true; 
  40.              */  
  41.             if (mCompleted && !mForceKillSystem) {  
  42.                 /** 
  43.                  * 设置waitedHalf的值为false,表示SystemServer中被监测的服务对象运行正常 
  44.                  */  
  45.                 waitedHalf = false;   
  46.                 continue;//则本次监控结束,返回继续下一轮监护。  
  47.             }  
  48.             /** 
  49.              * waitedHalf在监测对象运行正常时,一直被设置为false,只有当Watchdog监测到服务对象运行异常时才 
  50.              * 会被设置为true,因此在上一个30s周期内监测到服务对象运行异常,同时在本次30s周期内,waitedHalf 
  51.              * 没有重新设置为false,说明本周期内服务运行依然异常,就直接杀死SystemServer进程 
  52.              */  
  53.             if (!waitedHalf) {  
  54.                 ArrayList<Integer> pids = new ArrayList<Integer>();  
  55.                 pids.add(Process.myPid());  
  56.                 /** 
  57.                  * dump进程堆栈信息,将堆栈信息保存到/data/anr/traces.txt文件,同时dump出mediaserver, 
  58.                  * sdcard,surfaceflinger这三个native进程的堆栈信息,并发送进程退出信号 
  59.                  */  
  60.                 ActivityManagerService.dumpStackTraces(true, pids, nullnull,NATIVE_STACKS_OF_INTEREST);  
  61.                 SystemClock.sleep(3000);  
  62.                 /** 
  63.                  * RECORD_KERNEL_THREADS初始值为true,则dump出内核堆栈信息 
  64.                  */  
  65.                 if (RECORD_KERNEL_THREADS) {  
  66.                     dumpKernelStackTraces();  
  67.                     SystemClock.sleep(2000);  
  68.                 }  
  69.                 /** 
  70.                  * 设置waitedHalf的值为true,表示心跳HeartbeatHandler在monitor监测对象时,30s内没有顺利完成 
  71.                  */  
  72.                 waitedHalf = true;  
  73.                 /** 
  74.                  * 则本次监控结束,返回继续下一轮监测.这就说明当第一个30s监测到服务对象运行异常时,只是打印进程堆栈信息, 
  75.                  * 并不会杀死SystemServer进程 
  76.                  */  
  77.                 continue;  
  78.             }  
  79.         }  
  80.         /** 
  81.          * 若紧接着的下一轮监护,在30s内,monitor对象依旧未及时返回,直接运行到这里。这表示系统的监护对象有死锁现象发生, 
  82.          * SystemServer进程需要kill并重启。 
  83.          */  
  84.         final String name = (mCurrentMonitor != null) ?mCurrentMonitor.getClass().getName() : "null";  
  85.         Slog.w(TAG, "*** WATCHDOG IS GOING TO KILL SYSTEM PROCESS: " + name);  
  86.         EventLog.writeEvent(EventLogTags.WATCHDOG, name);  
  87.         ArrayList<Integer> pids = new ArrayList<Integer>();  
  88.         pids.add(Process.myPid());  
  89.         if (mPhonePid > 0) pids.add(mPhonePid);  
  90.         /** 
  91.          * 当Watchdog监测到服务对象运行异常时waitedHalf会被设置为true,这里传递的第一个参数为waitedHalf的取反,表示以追加的方式 
  92.          * 将进程堆栈信息保存到trace文件中 
  93.          */  
  94.         final File stack = ActivityManagerService.dumpStackTraces(  
  95.                 !waitedHalf, pids, nullnull, NATIVE_STACKS_OF_INTEREST);  
  96.         /** 
  97.          * 睡眠是为了等待完成进程堆栈信息的文件写操作 
  98.          */  
  99.         SystemClock.sleep(3000);  
  100.         if (RECORD_KERNEL_THREADS) {  
  101.             dumpKernelStackTraces();  
  102.             SystemClock.sleep(2000);  
  103.         }  
  104.         /** 
  105.          * 启动watchdogWriteToDropbox线程写dropbox错误日志 
  106.          */  
  107.         Thread dropboxThread = new Thread("watchdogWriteToDropbox") {  
  108.                 public void run() {  
  109.                     mActivity.addErrorToDropBox("watchdog"null"system_server"nullnull,  
  110.                             name, null, stack, null);  
  111.                 }  
  112.             };  
  113.         dropboxThread.start();  
  114.         try {  
  115.             dropboxThread.join(2000);  // wait up to 2 seconds for it to return.  
  116.         } catch (InterruptedException ignored) {}  
  117.         /** 
  118.          * 杀死SystemServer进程,从而引发Zygote进程自杀,并触发init进程重新启动Zygote进程,以达到手机重启目的 
  119.          */  
  120.         if (!Debug.isDebuggerConnected()) {  
  121.             Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);  
  122.             Process.killProcess(Process.myPid());  
  123.             System.exit(10);  
  124.         } else {  
  125.             Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");  
  126.         }  
  127.         waitedHalf = false;  
  128.     }  
  129. }  
run函数实现比较简单,周期性地设置mCompleted变量为假,通知心跳handler去调用各个monitor,而心跳handler会调用各个service的monitor,如果各个monitor都返回了,心跳handler会将mCompleted设置为真。否则,经过2次等待watchgod的run()发现mCompleted还为假,就证明hang了。在Watchdog线程中只是周期性地发送MONITOR消息以达到喂狗的效果,真正监测服务对象的任务在SystemServer的主线程中完成:
[java]  view plain  copy
  1. public void handleMessage(Message msg) {  
  2.     switch (msg.what) {  
  3.         /** 
  4.          * 接收到Watchdog线程发送过来的MONITOR消息 
  5.          */  
  6.         case MONITOR: {  
  7.             if (WATCHDOG_DEBUG) Slog.v(TAG, " **** 0-CHECK IF FORCE A REBOOT ! **** ");  
  8.             // See if we should force a reboot.  
  9.             int rebootInterval = mReqRebootInterval >= 0  
  10.                     ? mReqRebootInterval : Settings.Secure.getInt(  
  11.                     mResolver, Settings.Secure.REBOOT_INTERVAL,  
  12.                     REBOOT_DEFAULT_INTERVAL);  
  13.             if (mRebootInterval != rebootInterval) {  
  14.                 mRebootInterval = rebootInterval;  
  15.                 // We have been running long enough that a reboot can  
  16.                 // be considered...  
  17.                 checkReboot(false);  
  18.             }  
  19.   
  20.             if (WATCHDOG_DEBUG) Slog.v(TAG, " **** 1-CHECK ALL MONITORS BEGIN ! **** ");  
  21.             /** 
  22.              * 依次调用每个被监控的服务对象的monitor函数,以达到监控服务对象是否正常运行的目的 
  23.              */  
  24.             final int size = mMonitors.size();  
  25.             for (int i = 0 ; i < size ; i++) {  
  26.                 mCurrentMonitor = mMonitors.get(i);  
  27.                 mCurrentMonitor.monitor();  
  28.             }  
  29.             if (WATCHDOG_DEBUG) Slog.v(TAG, " **** 2-CHECK ALL MONITORS FINISHED ! **** "); //如果监护的对象都正常,则会很快运行到这里,并对mCompleted赋值为true,表示对象正常返回。mCompleted值初始为false。  
  30.             /** 
  31.              * 如果在30s内所有的服务对象的monitor函数都能顺利返回,说明服务运行正常,这时就修改mCompleted的值为true 
  32.              * 告知Watchdog线程服务的运行状态,由于Watchdog线程周期性地判断mCompleted的值以达到查询服务运行状态的目的, 
  33.              * 因此这里必须使用线程同步机制 
  34.              */  
  35.             synchronized (Watchdog.this) {  
  36.                 mCompleted = true;  
  37.                 mCurrentMonitor = null;  
  38.             }  
  39.             if (WATCHDOG_DEBUG) Slog.v(TAG, " **** 3-SYNC Watchdog.THIS FINISHED ! ****");  
  40.             if (WATCHDOG_DEBUG) Slog.v(TAG, " ");  
  41.         } break;  
  42.     }  
  43. }  
每个注册到WatchDog服务中的监测对象对必须实现WatchDog.Monitor接口,同时必须实现该接口中的monitor方法,这些被监控的服务在monitor函数中都做了什么工作呢?对于ActivityManagerService来说,其实现的monitor函数如下:
[java]  view plain  copy
  1. public void monitor() {  
  2.     synchronized (this) { }  
  3. }  
在ActivityManagerService服务实现的其他函数中,用于线程同步的锁都是ActivityManagerService对象自身,这里的monitor函数只是简单地去请求这个锁,如果ActivityManagerService服务运行正常,即没有发送线程死锁等,请求这个锁是很快完成的,即monitor函数可以顺利返回,但是如果ActivityManagerService在执行过程中发生线程死锁,即其他执行函数始终占用锁,monitor函数不能及时请求到该锁,也即无法正常返回,心跳HeartbeatHandler不能及时设置标志位mCompleted的值,从而告知Watchdog线程被监测的对象运行有异常,让Watchdog线程杀死SystemServer进程。SystemServer监控重要service,重要service hang则SystemServer死,SystemServer死则Zygote监控到,Zygote也死并且杀死整个Java世界,Zygote死则init监控到,init重新启动Zygote,之后SystemServer、service又进入重生过程。

2


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值