Android Watchdog(看门狗)分析

一、在嵌入式设备上的应用

Watch Dog的中文意思是“看门狗”,最初是应用子啊嵌入式设备上的,目的是为了防止程序跑飞,所以专门设置了一个硬件看门狗,每隔一段时间,看门狗就会去检查一下某个参数是不是被设置了,如果发现该参数设置出错,就会强制重启程序。

二、在Android上的应用

Android对SystemServer参数是否被设置时很谨慎的,所以专门为它增加了看门狗,可他到底看哪个门呢?就是看几个重要的Service门,如果Android一旦发现几个重要的Service门出问题,就会马上杀掉进程system_server,而这也会使zygote一起自杀,最后导致重启Java世界。

三、Android中的Watchdog分析

我们先把SystemServer使用Watchdog的调用流程总结一下,然后以为为切入点来分析Watchdog。system_server和Watchdog的交互流程可以总结为一下三个步骤:

a、Watchdog.getInstance().init();

b、Watchdog.getInstance().start();

c、Watchdog.getInstance().addMonitor();

这三个步骤都很简单。先看第一步。

getInstance用户创建Watchdog,代码如下:

【-->Watchdog.java】

public static Watchdog getInstance(){

if(sWatchdog == null){

sWatchdog = new Watchdog();//使用了单例模式

}

return sWatchdog;


public class Watchdog extends Thread{

//Watchdog从线程类派生,所以它会在一个单独的线程中执行

private Watchdog(){

mHandler = new HeartbeatHandler();

//GlobalPssCollected和内存信息有关

mGlobalPsCollected = new GlobalPssCollected();

}


public void init(Context context,BatteryService battery,PowerManagerService power,AlarmManagerService alarm,ActivityManagerService activity){

mResolver = context.getContentResolver();

mBattery = battery;

mPower = power;

mAlarm =  alarm;

mActivity = activity;

.....

mBootTime = System.currentTimeMillis();//得到当前时间

......

}

到这里,看门狗就诞生了,下面就让他动起来。

2、让看门狗跑起来

SystemServer调用Watchdog的start函数,这将导致Watchdog的run在另外一个线程中被执行。代码如下:

【-->Watchdog.java】

public void run(){

boolean waitedHalf = false;

while(true){

mCompleted = false;//false表示各国服务的检查还未完成。

//mHandler的消息处理是在另外一个线程中,这里将给那个线程发消息,请求Watchdog检查Service是否正常工作。

mHandler.sendEmptyMessage(MONITOR);

synchronized(this){

long timeout = TIME_TO_MAIT;

long start = SystemClock.uptimeMillis();

//注意这个小while循环的条件,mForceKillSystem为true时也会导致推出循环。

while(timeout > 0 && !mForceKillSystem){

try{

wait(timeout);//等待检查的结果

}catch{

}

timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);

}

//mCompleted为true,表示service一切正常

if(mCompleted && !mForceKillSystem){

waitedHalf = false;

continue;

}

//如果mCompleted不为true,看门狗会尽责的再检查一次。

if(!waitedHalf){

......

waitedHalf = true;

continue;//再检查一次

}

}

//已经检查两次了,如果再出现,这回真的有问题了,所以system_server需要将自己干掉。

if(!Debug.idDebuggerConncted()){

Process.killProcess(Process.myPid());

System.exit(10);//干掉自己

}

......

waiteHalf = false;

}

}


上面Run方法里的意思是:

隔一段时间给另外一个线程发送一条MONITOR消息,哪个线程将检查各个Service的健康情况。而看门狗会等待检查结果,如果第二次还没有返回结果,那么就会杀死进程systen_server。

下面我们看看线程是怎么检查Service的。

3、列队检查

这么多的Service,看门狗到底是检查哪个呢?答案是一共有三个Service需要交给Watchgod检查:

a、ActivityManagerService

b、PowerManagerService

c、WindowManagerService

要想支持看门狗的检查,就需要让这些Service实现monitor接口,然后Watchdog就会调用它们的monitor函数进行检查了。检查的地方时在HeartbeatHandler类的handleMessage中,代码如下:

【-->Watchdog.java::HeartbeatHandler】

final class HearbeatHandler extends Handler{

@Overode

public void handleMessage(Message msg){

switch(msg.what){

......

case MONITOR:{

......

logg now = SystemClock.uptimeMillis();

final int size = mMontitors.size();

//检查各个服务,并设置当前检查对象为mCurrentMonitor。

for(int i = 0;i<size,i++){

mCurrentMonitor = mMonitors.get(i);

mCurrentMonitor .monitor();//检查这个对象

}

//如果没问题,则设置mCurrentMonitor.monitor();//检查这个对象

synchronized(Watchdog.this){

mCompleted = true;

mCurrentMonitor = null;

}

} break;

}

}

}

那么Service的健康状况是怎么判读呢?我们以PowerManagerService为例,先看看它是怎么把自己交给看门狗检查的,代码入下:

【-->PowerManagerService.java】

PowerManagerService(){

......

//z在构造函数中把自己加入Watchdog的检查队列

Watchdog.getInstance().addMonitor(this);

}

而Watchdog调用各个monitor函数到底又检查了些什么呢?看看它的实现monitor函数吧!

【-->PowerManagerService.java】

public void monitor(){

//原来monitor检查的就是这些Service是否发生死锁了!

synchronized(mLocks){}

}

原来,Watchdog最怕系统服务死锁了,对于这种情况也只能采取杀死进程的办法了。












你可能感兴趣的:(Android Watchdog(看门狗)分析)