Android 中的看门狗—Watchdog


Android 中的看门狗—Watchdog
一、SystemServer 进程中初始化、启动看门狗..................................................................... 1
二、AMS 实现接口Watchdog.Monitor.................................................................................... 3
三、Watchdog.java 的实现........................................................................................................4
四、常见问题分析.....................................................................................................................5
在android 系统中,看门狗可以分成以下两种类型。
1)、HW Watchdog:用于监测CPU 执行是否异常, 启用Kernel RT
thread tick HW watchdog 来达成, 如果异常, 则重启整个系统。
2)、System Server Watchdog:用于监测Android System Server 关键
线程和资源使用是否正常, 如果异常则重启android 上层。
今天我们主要分析的是SystemServer 进程中的看门狗:
一、SystemServer 进程中初始化、启动看门狗
1.1、初始化:
SystemServer 进程中,在开启otherservice 服务的方法中,会初始
化看门狗Watchdog 的实例对象。源码如下所示:
traceBeginAndSlog("InitWatchdog");
final Watchdog watchdog = Watchdog.getInstance();
watchdog.init(context, mActivityManagerService);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
在这里我们可以自动切换到Watchdog.java 类中的init()方法查看
发现,首先,它会通过registerReceive(r )方法注册一个广播接收reboot
重启的请求; 其次, 通过ExceptionLog 的实例对象, 进行监护
SystemServer 进程。这也就是Watchdog 的主要作用。
1.2、启动:
在AMS 实例对象调用systemReady()函数中,有这么一句启动
看门狗的代码:Watchdog.getInstance().start();注意,systemReady()
方法主要是告知各个服务系统已经准备就绪,可以开始实现各自的职
责。
1.3、SystemServer 中被看门狗监控的三大服务:
1)、ActivityManagerService.java
path:./frameworks/base/services/core/java/com/android/server/am/
2)、PowerManagerService.java
path:./frameworks/base/services/core/java/com/android/server/power/
3)、WindowManagerService.java
path:./frameworks/base/services/core/java/com/android/server/wm/
因此,WatchDog 主要就是确保上述的服务发生死锁之后,退出
SystemServer 进程,让init 进程重启它,让系统回到可用状态。
由于上述服务实现看门狗的过程都类似,这里我们只以AMS 为例
进行分析。
二、AMS 实现接口Watchdog.Monitor
每个被监护的Service 服务必须实现看门狗的”Watchdog.Monitor”
接口。如`public final class ActivityManagerService extends
ActivityManagerNative implements Watchdog.Monitor,
BatteryStatsImpl.BatteryCallback` 。这个接口很简单, 就只有一个
monitor()方法。其次,在AMS 中实现的这个方法也只是锁一下对象,
什么都没有做,直接返回。如:
/** In this method we try to acquire our lock to make sure that we have
not deadlocked */
public void monitor() {
synchronized (this) { }
}
从它的注释中也可以看出来“在这个方法中,我们试图获得锁,以确
保我们没有死锁。”
Note:实现完接口之后,其实,它在AMS 的构造函数中有这么两行代
码:

Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
“ ,其作用是把AMS 注册到Watchdog 服务中。
三、Watchdog.java 的实现
1、由于Watchdog 是Thread 的子类,我们首先来看它的run()方法。
public void run() {
boolean waitedHalf = false;
boolean mSFHang = false;
while (true) {
.......
for (int i=0; i<mHandlerCheckers.size(); i++) { //调用HandlerChecker 线程
HandlerChecker hc = mHandlerCheckers.get(i);
hc.scheduleCheckLocked();
}
.......
while (timeout > 0) { //等待超时时间,判断是否退出循环
if (Debug.isDebuggerConnected()) {
debuggerWasConnected = 2;
}try { wait(timeout);
} catch (InterruptedException e) { }
if (Debug.isDebuggerConnected()) {
debuggerWasConnected = 2;
}
timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start);}
...........
// Only kill the process if the debugger is not attached.
if (Debug.isDebuggerConnected()) { //出现死锁,杀死SystemServer 进程
debuggerWasConnected = 2;
}
if (debuggerWasConnected >= 2) {
Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the
system process");...............
Note:在Watchdog 的run()方法中会去调用子线程HandlerChecker 检查
各个Service 服务是否正常工作,此时的看门狗会不断的去检查并且等待它反馈
回来的结果,如果出现死锁的情况,立马杀掉SystemServer 进程。而且这其中如
果超时,会利用debuggerd 打印backtrace 到/proc/sysrq-trigger 当中。
2、HandlerChecker 的run()方法。源码如下所示:
public void run() {
final int size = mMonitors.size(); // 获取注册Watchdog 服务的
Services 数量
for (int i = 0 ; i < size ; i++) {
synchronized (Watchdog.this) {
mCurrentMonitor = mMonitors.get(i); //
}
mCurrentMonitor.monitor();
}
synchronized (Watchdog.this) { //如果没有死锁一般都会走到这里
mCompleted = true; //表示正常
mCurrentMonitor = null; //没有死锁
}
}
Note:如果被看门狗监护的服务对象发生了死锁,则线程会一直阻塞在这里。前
面提到了许多”死锁”,死锁?无非就是系统中各个进程互相抢占资源的过程中导
致的一种现象。对于死锁的产生原因非常多,比如说java 层死锁可能发生在调
用native 函数,而native 函数可能与硬件交互导致时间过长而没有返回,从而导
致长时间占用导致问题。具体问题具体分析。
最后,附上一张总时序图~:
SystemServer Watchdog Thread(this) HandlerChecker AMS
1 : addmonitor()
2 : new Watchdog()
3 : start()
4 : run()
5 : scheduleCheckLocked()
6 : timeout() 7 : mCurrentMonitor.monitor()
8 : mCompleted=true()
9 : Service is normal()
10 : Please Killing SystemService()
四、常见问题分析
注:抓取MTK3710 的开关机log,查看ksernerl log 对比下面的信息
看门狗在检查各个Service 的过程中,分下面三种情形做出一次举动,
第一种情形已经过验证,下面两种情形还未实验:
1)、正常情况下,tick 300s, 对应count=10.
[ 66.841723]: (0)[1147:watchdog]AEEIOCTL_RT_MON_Kick ( 300)
[ 66.841753]: (0)[1147:watchdog][Hang_Detect] hang_detect enabled 10
2)、在dump backtrace 时,tick 600s, 对应count=20.
[ 258.218145] (0)[1322:watchdog]AEEIOCTL_RT_MON_Kick ( 600)
[ 258.218171] (0)[1322:watchdog][Hang_Detect] hang_detect enabled 20
3)、在SWT 发生的情况下,tick 720s, 对应count=24.
[ 299.046542] (0)[1322:watchdog]AEEIOCTL_RT_MON_Kick ( 720)
[ 299.046572] (0)[1322:watchdog][Hang_Detect] hang_detect enabled 24
其次,一条可以快速定位是否是进程卡住的问题,正常情况下Kernel threrad
打印的信息:
[ 60.561702]: (0)[118:hang_detect][Hang_Detect] hang_detect thread counts down
10:10.

猜你喜欢

转载自blog.csdn.net/Toc_SunWinner/article/details/79314732
今日推荐