对手机系统而言,因为肩负着接听电话和接收短信的“重任”,所以被寄予7x24小时正常工作的希望。但是基于成本,普通的手机系统很难做到完全不出故障。但是大部分的故障都会做重启后消失,不会影响继续使用。所以简单的办法是,如果检测到系统不正常了,将设备重新启动,这样用户就能继续使用了。那么如何才能判断系统是否正常呢。通常的做法是在设备中增加一个硬件看门狗,软件系统必须定时的向看门狗硬件中写值来表示自己没出故障(俗称“喂狗”),否则超过了规定的时间看门狗就会重新启动设备。在Init进程一章中我们介绍了watchdogd守护进程,这个守护进程就是用来喂硬件看门狗的。
硬件看门狗的问题是它的功能比较单一,只能监控整个系统。早期的手机操作系统大多是单任务的,硬件看门狗勉强能胜任。Android的SystemServer是一个非常复杂的进程,里面运行的服务超过五十种,是最可能出问题的进程,因此有必要对SystemServer中运行的各种线程实施监控。但是如果使用硬件看门狗的工作方式,每个线程隔一段时间去喂狗,不但非常浪费CPU,而且会导致程序设计更加复杂。因此Android开发了WatchDog类作为软件看门狗来监控SystemServer中的线程。一旦发现问题,WatchDog会杀死SystemServer进程。
SystemServer的父进程Zygote接收到SystemServer的死亡信号后,会杀死自己。Zygote进程死亡的信号传递到Init进程后,Init进程会杀死Zygote进程所有的子进程并重启Zygote。这样整个手机相当于重启一遍。通常SystemServer出现问题和kernel并没有关系,所以这种“软重启”大部分时候都能够解决问题。而且这种“软重启”的速度更快,对用户的影响也更小。
运行在Binder线程中的方法如果需要使用了全局的资源,就必须建立临界区来实施保护。通常的做法是使用synchronized关键字。例如:
synchronized (mLock) {
......
}
这样,我们可以通过锁mLock被持有的时间来判断服务是否正常。
而判断一个线程是否正常的方法是给这个线程发送消息,如果消息不能在规定的时间内得到处理就表明线程出问题了。
WatchDog运行在一个单独的线程中,它的线程执行方法run()的代码如下:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
代码清单
10.2
run()方法中有一个无限循环,每次循环中主要做三件事:
1.
publicvoid scheduleCheckLocked() {
}
HandlerChecker对象即要监控服务,也要监控某个线程。所以上面的代码先判断mMonitors的size是否为0。如果为0,说明这个HandlerChecker没有监控服务,这时如果被监控线程的消息队列处于空闲状态(调用isIdling()检查),则说明线程运行良好,把mCompleted设为true后就可以返回了。否则先把mCompleted设为false,然后记录消息开始发送的时间到变量mStartTime中,最后调用postAtFrontOfQueue()方法给被监控的线程发送一个消息。这个消息的处理方法是HandlerChecker类的方法run(),代码如下:
publicvoid run() {
}
如果消息处理方法run()能够被执行,说明受监控的线程本身没有问题。但是还需要检查被监控服务的状态。检查是通过调用服务中实现的monitor()方法来完成的。通常monitor()方法的实现是获取服务中的锁,如果不能得到,线程就会被挂起,这样mCompleted的值就不能被置成true了。
mCompleted的值为true,表明HandlerChecker对象监控的线程或服务正常。否则就可能有问题。是否真有问题还要通过等待的时间是否超过规定时间来判断。
moninor()方法的实现通常如下:
publicvoid monitor() {
}
2.
3.
前面的代码清单10.2第25行调用了方法evaluateCheckerCompletio
privateint evaluateCheckerCompletio
}
evaluateCheckerCompletio
1)
2)
3)
4)
evaluateCheckerCompletio
前面的代码清单10.2中的第26到40行在对返回的状态值做判断,只要不是OVERDUE状态都可以继续执行。否则就会杀死SystemServer进程。
其实这里使用三种状态就足够了:COMPLETED,WAITING和OVERDUE。WAITED_HALF这种状态是为了调试性能用的。如果某个线程或服务的执行时间超过了规定时间的一半,表明可能会出问题,系统就会把它的信息输出到Log中。这样开发人员通过查看Log就能看到潜在的问题,方便进行改善。参见代码清单10.2中的第35行。
getCompletionStateLocked
public intgetCompletionStateLocked
}
getCompletionStateLocked
原文地址:http://blog.csdn.net/u013234805/article/details/24796615