您的位置:首页 > 移动开发 > Android开发

Android软Watchdog源码分析

2014-05-22 19:09 225 查看
分类: 【Android 系统分析】2013-09-07
10:52 706人阅读 评论(0) 收藏 举报

AndroidWatchdogSystemServer看门狗

目录(?)[+]

在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
plaincopy

Slog.i(TAG, "Init Watchdog");

Watchdog.getInstance().init(context, battery, power, alarm,ActivityManagerService.self());

Watchdog.getInstance().start();

Watchdog采用单例模式构造对象

[java] view
plaincopy

public static Watchdog getInstance() {

if (sWatchdog == null) {

sWatchdog = new Watchdog();

}

return sWatchdog;

}

Watchdog构造过程

[java] view
plaincopy

private Watchdog() {

super("watchdog");

mHandler = new HeartbeatHandler();

}

在构造Watchdog时创建了一个心跳HeartbeatHandler,用于处理Watchdog线程发送的MONITOR消息。接着调用Watchdog的init函数来初始化Watchdog对象:

[java] view
plaincopy

public void init(Context context, BatteryService battery,

PowerManagerService power, AlarmManagerService alarm,

ActivityManagerService activity) {

mResolver = context.getContentResolver();

mBattery = battery;

mPower = power;

mAlarm = alarm;

mActivity = activity;

//注册重启广播接收器

context.registerReceiver(new RebootReceiver(),new IntentFilter(REBOOT_ACTION));

mRebootIntent = PendingIntent.getBroadcast(context,0, new Intent(REBOOT_ACTION), 0);

//注册重启请求广播接收器

context.registerReceiver(new RebootRequestReceiver(),

new IntentFilter(Intent.ACTION_REBOOT),

android.Manifest.permission.REBOOT, null);

mBootTime = System.currentTimeMillis();

}

RebootReceiver负责接收由AlarManagerService发出的PendingIntent,并进行系统重启。

RebootRequestReceiver负责接收系统内部发出的重启Intent消息,并进行系统重启。

添加监控对象

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

InputManagerService

MountService

NativeDaemonConnector

NetworkManagementService

PowerManagerService

WindowManagerService

Watchdog提供了addMonitor方法来添加监控对象

[java] view
plaincopy

public void addMonitor(Monitor monitor) {

synchronized (this) {

if (isAlive()) {

throw new RuntimeException("Monitors can't be added while the Watchdog is running");

}

mMonitors.add(monitor);

}

}

添加过程只是将需要被Watchdog监控的对象添加到Watchdog的动态monitor数组mMonitors中。

Watchdog监控过程

当调用Watchdog.getInstance().start()将启动Watchdog线程,Watchdog执行过程如下:

[java] view
plaincopy

public void run() {

boolean waitedHalf = false;

while (true) {

/**

* 反复设置mCompleted变量为false

*/

mCompleted = false;

/**

* 发送一个MONITOR消息给心跳HeartbeatHandler处理,处理过程就是调用各个监控对象的monitor函数,

* 如果各个被监控服务的monitor都顺利返回,心跳HeartbeatHandler会将mCompleted设置为true

*/

if (mHandler.sendEmptyMessage(MONITOR)) {

if (WATCHDOG_DEBUG) Slog.v(TAG,"**** -1-Watchdog MSG SENT! ****");

}

/**

* Watchdog线程和SystemServer主线程共用同一个消息队列,为了在两个线程中改变mCompleted的值,这里必须使用线程同步机制

*/

synchronized (this) {

/**

* TIME_TO_WAIT的默认时间为30s。此为第一次等待时间,WatchDog判断对象是否死锁的最长处理时间为1Min。

*/

long timeout = TIME_TO_WAIT;

/**

* 获取当前时间

*/

long start = SystemClock.uptimeMillis();

/**

* 等待30秒,等待HeartbeatHandler的处理结果。然后才会进行下一步动作。

*/

while (timeout > 0 && !mForceKillSystem) {

try {

wait(timeout); // notifyAll() is called when mForceKillSystem is set

} catch (InterruptedException e) {

Log.wtf(TAG, e);

}

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

}

/**

* 如果所有监控对象在30s内能够顺利返回,则会得到mCompleted = true;

*/

if (mCompleted && !mForceKillSystem) {

/**

* 设置waitedHalf的值为false,表示SystemServer中被监测的服务对象运行正常

*/

waitedHalf = false;

continue;//则本次监控结束,返回继续下一轮监护。

}

/**

* waitedHalf在监测对象运行正常时,一直被设置为false,只有当Watchdog监测到服务对象运行异常时才

* 会被设置为true,因此在上一个30s周期内监测到服务对象运行异常,同时在本次30s周期内,waitedHalf

* 没有重新设置为false,说明本周期内服务运行依然异常,就直接杀死SystemServer进程

*/

if (!waitedHalf) {

ArrayList<Integer> pids = new ArrayList<Integer>();

pids.add(Process.myPid());

/**

* dump进程堆栈信息,将堆栈信息保存到/data/anr/traces.txt文件,同时dump出mediaserver,

* sdcard,surfaceflinger这三个native进程的堆栈信息,并发送进程退出信号

*/

ActivityManagerService.dumpStackTraces(true, pids, null, null,NATIVE_STACKS_OF_INTEREST);

SystemClock.sleep(3000);

/**

* RECORD_KERNEL_THREADS初始值为true,则dump出内核堆栈信息

*/

if (RECORD_KERNEL_THREADS) {

dumpKernelStackTraces();

SystemClock.sleep(2000);

}

/**

* 设置waitedHalf的值为true,表示心跳HeartbeatHandler在monitor监测对象时,30s内没有顺利完成

*/

waitedHalf = true;

/**

* 则本次监控结束,返回继续下一轮监测.这就说明当第一个30s监测到服务对象运行异常时,只是打印进程堆栈信息,

* 并不会杀死SystemServer进程

*/

continue;

}

}

/**

* 若紧接着的下一轮监护,在30s内,monitor对象依旧未及时返回,直接运行到这里。这表示系统的监护对象有死锁现象发生,

* SystemServer进程需要kill并重启。

*/

final String name = (mCurrentMonitor != null) ?mCurrentMonitor.getClass().getName() : "null";

Slog.w(TAG, "*** WATCHDOG IS GOING TO KILL SYSTEM PROCESS: " + name);

EventLog.writeEvent(EventLogTags.WATCHDOG, name);

ArrayList<Integer> pids = new ArrayList<Integer>();

pids.add(Process.myPid());

if (mPhonePid > 0) pids.add(mPhonePid);

/**

* 当Watchdog监测到服务对象运行异常时waitedHalf会被设置为true,这里传递的第一个参数为waitedHalf的取反,表示以追加的方式

* 将进程堆栈信息保存到trace文件中

*/

final File stack = ActivityManagerService.dumpStackTraces(

!waitedHalf, pids, null, null, NATIVE_STACKS_OF_INTEREST);

/**

* 睡眠是为了等待完成进程堆栈信息的文件写操作

*/

SystemClock.sleep(3000);

if (RECORD_KERNEL_THREADS) {

dumpKernelStackTraces();

SystemClock.sleep(2000);

}

/**

* 启动watchdogWriteToDropbox线程写dropbox错误日志

*/

Thread dropboxThread = new Thread("watchdogWriteToDropbox") {

public void run() {

mActivity.addErrorToDropBox("watchdog", null, "system_server", null, null,

name, null, stack, null);

}

};

dropboxThread.start();

try {

dropboxThread.join(2000); // wait up to 2 seconds for it to return.

} catch (InterruptedException ignored) {}

/**

* 杀死SystemServer进程,从而引发Zygote进程自杀,并触发init进程重新启动Zygote进程,以达到手机重启目的

*/

if (!Debug.isDebuggerConnected()) {

Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);

Process.killProcess(Process.myPid());

System.exit(10);

} else {

Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");

}

waitedHalf = false;

}

}

run函数实现比较简单,周期性地设置mCompleted变量为假,通知心跳handler去调用各个monitor,而心跳handler会调用各个service的monitor,如果各个monitor都返回了,心跳handler会将mCompleted设置为真。否则,经过2次等待watchgod的run()发现mCompleted还为假,就证明hang了。在Watchdog线程中只是周期性地发送MONITOR消息以达到喂狗的效果,真正监测服务对象的任务在SystemServer的主线程中完成:

[java] view
plaincopy

public void handleMessage(Message msg) {

switch (msg.what) {

/**

* 接收到Watchdog线程发送过来的MONITOR消息

*/

case MONITOR: {

if (WATCHDOG_DEBUG) Slog.v(TAG, " **** 0-CHECK IF FORCE A REBOOT ! **** ");

// See if we should force a reboot.

int rebootInterval = mReqRebootInterval >= 0

? mReqRebootInterval : Settings.Secure.getInt(

mResolver, Settings.Secure.REBOOT_INTERVAL,

REBOOT_DEFAULT_INTERVAL);

if (mRebootInterval != rebootInterval) {

mRebootInterval = rebootInterval;

// We have been running long enough that a reboot can

// be considered...

checkReboot(false);

}

if (WATCHDOG_DEBUG) Slog.v(TAG, " **** 1-CHECK ALL MONITORS BEGIN ! **** ");

/**

* 依次调用每个被监控的服务对象的monitor函数,以达到监控服务对象是否正常运行的目的

*/

final int size = mMonitors.size();

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

mCurrentMonitor = mMonitors.get(i);

mCurrentMonitor.monitor();

}

if (WATCHDOG_DEBUG) Slog.v(TAG, " **** 2-CHECK ALL MONITORS FINISHED ! **** "); //如果监护的对象都正常,则会很快运行到这里,并对mCompleted赋值为true,表示对象正常返回。mCompleted值初始为false。

/**

* 如果在30s内所有的服务对象的monitor函数都能顺利返回,说明服务运行正常,这时就修改mCompleted的值为true

* 告知Watchdog线程服务的运行状态,由于Watchdog线程周期性地判断mCompleted的值以达到查询服务运行状态的目的,

* 因此这里必须使用线程同步机制

*/

synchronized (Watchdog.this) {

mCompleted = true;

mCurrentMonitor = null;

}

if (WATCHDOG_DEBUG) Slog.v(TAG, " **** 3-SYNC Watchdog.THIS FINISHED ! ****");

if (WATCHDOG_DEBUG) Slog.v(TAG, " ");

} break;

}

}

每个注册到WatchDog服务中的监测对象对必须实现WatchDog.Monitor接口,同时必须实现该接口中的monitor方法,这些被监控的服务在monitor函数中都做了什么工作呢?对于ActivityManagerService来说,其实现的monitor函数如下:

[java] view
plaincopy

public void monitor() {

synchronized (this) { }

}

在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又进入重生过程。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: