1. android framework层中的watchdog,它属于一种软件Watchdog实现。
a.接收系统内部reboot请求,重启系统。
b.监护SystemServer进程,防止系统死锁, 确保ActivityManagerService、WindowManagerService和 PowerManageService发生死锁后,退出SystemServer进程,让init进程重启它,让系统回到可用状态。
2. 分析framework/base/services/java/com/android/server/watchdog.java, watchdog实际上是一个thread
3. WatchDog如何启动, run@Frameworks/base/services/java/com/android/server/SystemServer.java
WatchDog是在SystemServer进程中被初始化和启动的。在SystemServer 被Start时,各种Android服务被注册和启动,其中也包括了WatchDog的初始化和启动。代码如下:
Watchdog.getInstance().init(context, battery, power, alarm,ActivityManagerService.self());
在SystemServer Run函数的后半段,将检查系统是否已经准备好运行第三方代码,并通过SystemReady接口通知系统已经就绪。在ActivityManagerService的SystemReady接口的CallBack函数中实现WatchDog的启动,代码如下
Watchdog.getInstance().start();
4. 在WatchDog启动之后,开始跑run函数。该函数内部为一个无限循环。
public void run() {
boolean waitedHalf = false;
while (true) {
mCompleted = false;
mHandler.sendEmptyMessage(MONITOR);
...
while (timeout > 0 && !mForceKillSystem) {
try {
wait(timeout);
} catch (InterruptedException e) {
}
timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
//TIME_TO_WAIT的默认时间为30s。此为第一次等待时间,WatchDog判断对象是否死锁的最长处理时间为1Min。
}
...
}
}
一开始就会发送一个MONITOR的Message,由HeartbeatHandler负责接收并处理。同时会等待30秒,等待HeartbeatHandler的处理结果。然后才会进行下一步动作。
在HeartbeatHandler中将会作如下处理:
public void handleMessage(Message msg) {
switch (msg.what) {
case MONITOR: {
...
final int size = mMonitors.size();
for (int i = 0 ; i < size ; i++) {
mCurrentMonitor = mMonitors.get(i);
mCurrentMonitor.monitor();
}//依次去调用监护对象的monitor接口,实现对其的监护。如果monitor中的synchronized(..)不能及时返回,则表明该监护对象被lock了
synchronized (Watchdog.this) {
mCompleted = true;
mCurrentMonitor = null;
}//如果监护的对象都正常,则会很快运行到这里,并对mCompleted赋值为true,表示对象正常返回。mCompleted值初始为false。
同时在run函数中:if (mCompleted && !mForceKillSystem) {
// The monitors have returned.
waitedHalf = false;
continue;
}//如果所有对象在30s内能够返回,则会得到mCompleted = true;则本次监护就结束,返回继续下一轮监护。
如果在30s内,monitor对象未能返回,mCompleted 值即为false,则会运行到该语句:
if (!waitedHalf) {
// We've waited half the deadlock-detection interval. Pull a stack
// trace and wait another half.
ArrayList<Integer> pids = new ArrayList<Integer>();
pids.add(Process.myPid());
ActivityManagerService.dumpStackTraces(true, pids, null, null);
waitedHalf = true;
continue;
}//会调用ActivityManagerService.java中的dumpStackTraces接口函数。
该动作发生在第一次等待的30s时间内,monitor对象未返回,由于在调用完ActivityManagerService.java的dumpStackTraces接口函数后,将waitedHalf赋值为true。并返回继续下一轮监护。若紧接着的下一轮监护,在30s内 monitor对象依旧未及时返回,此时
if (mCompleted && !mForceKillSystem){
...
}
if (!waitedHalf){
...
}//此时这两个语句都不会运行,则会直接运行到下面部分。这表示系统的监护对象有死锁现象发生,SystemServer进程需要kill并重启。
// If we got here, that means that the system is most likely hung.
...
// Pull our own kernel thread stacks as well if we're configured for that
if (RECORD_KERNEL_THREADS) {
dumpKernelStackTraces();//-->dumpKernelStacks@frameworks/base/core/jni/android_server_watchdog.cpp,后面会分析
}
// Only kill/crash if the debugger is not attached.
if (!Debug.isDebuggerConnected()) {
if (Build.TYPE.equals("eng") || Build.TYPE.equals("userdebug")) {
Slog.w(TAG, "*** WATCHDOG KILLING THE SYSTEM: " + name);
// Give some extra time to make sure CrashMonitorService reacts to
// the dropbox entry before the crash
SystemClock.sleep(2000);
forceCrashDump();//通过写入"c"到"/proc/sysrq-trigger"产生kernel crash,启动kernel crash dump
} else {
Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
Process.killProcess(Process.myPid());
System.exit(10);//在剩下的30s内,做一些收尾工作,如重新初始化trace file。最后直接将SystemServer进程kill,并且退出系统。Init进程会重新启动SystemServer进程,让其回到可用状态。System.exit(?)应该是退出进程???会终止该java程序的JVM
}
} else {
Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
}
5. 由以上分析可知,如果监控的所有service没有被lock, watchdog thread会30秒心跳一次[HeartbeatHandler.sendEmptyMessage(MONITOR);];如果30秒后所监控的service有被lock的,则进入half lock状态,并做一些前期工作,应对完全死锁full lock; 如果在接下来的30秒,service都被解除lock,则表示又活过来了,重新开始30秒一次的心跳;如果没有在接下来的30秒中解除lock,则认为系统死锁了,开始处理死锁过程。
6. 如何使用watchdog monitor service,在 ActivityManagerService.java,PowerManagerService.java,WindowManagerService.java中有
a. Watchdog.getInstance().addMonitor(this);//增加该service 到wathdog中的monitor list中
b. @PowerManagerService.java 中有
public void monitor() {
synchronized (mLocks) { }
}
c. @WindowManagerService.java 中有
public void monitor() {
synchronized (mWindowMap) { }
synchronized (mKeyguardTokenWatcher) { }
}
d. @ActivityManagerService.java 中有
public void monitor() {
synchronized (this) { }
}
e. 从代码中可以看到,用于monitor中的synchronized对象,也是被service 其他关键处理函数用到的synchronized对象;
f. 简而言之,android的watchdog 机制,是基于java 的synchronized 锁对象机制,很巧妙的应用!!!!
7. 如果被监控的service 中关键处理过程或函数,超过1分钟没有完成,则触发android watchdog.
8. 分析dumpKernelStackTraces@frameworks/base/services/java/com/android/server/watchdog.java --> native_dumpKernelStacks-->dumpKernelStacks@frameworks/base/core/jni/android_server_watchdog.cpp
a. 主要从 proc/<process id>/task 下获取当前process所有的thread 的ID
b. dumpOneStack函数获取 proc/<thread id>/stack 的dump 信息
9. 分析如果发生死锁后,非userdebug和eng版本,init 如何重启watchdog thread和 SystemServer thread???
a. init.rc中有
service servicemanager /system/bin/servicemanager //该源代码位于 frameworks/base/cmds/servicemanager/目录下
user system
critical
onrestart restart zygote
onrestart restart media
b. main@system/core/init/init.c中有一死循环会不断执行restart_processes-->service_for_each_flags-->restart_service_if_needed-->service_start, 检查是否*.rc申明的所有 非ONESHOT的service,是否已经停止,如果停止则需要重新启动该service. 好像和死锁重启无关???
b. init.rc中还有
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-s erver
socket zygote stream 660 root system
onrestart write /proc/sysrq-trigger c
在后面的分析中如何 关键的三个service发生dead lock, zygote将会exit,然后init process会重启zygote --> system_server
c. startSystemServer@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中有
"--nice-name=system_server",
"com.android.server.SystemServer",
指明了线程system_server 就是com.android.server.SystemServer, 也就是zygote会启动运行com.android.server.SystemServer
d. $adb shell ps 可以看到
root 1483 1 97632 28912 c011e7ec afd0b944 S zygote
system 1756 1483 196400 41324 ffffffff afd0b7fc S system_server
e. #ls /proc/1756/task 可以看到process system_server 启动的所有thread ID,比如 1756,1757,...; 进入1757目录,#cat status可以看到该thread的具体信息。
f. 执行sh脚本
adb shell ls proc/1756/task > dirlist
while read one; do
temp=`expr substr $one 1 4`
adb shell cat proc/1756/task/${temp}/status | grep -E "Name:|Tgid:|Pid:|PPid:"
echo "----------------------------------------------------------"
done <dirlist
有很多关键线程都是被system_server即com.android.server.SystemServer创建,如HeapWorker,GC,Binder,ProcessStats,PowerManagerService,WindowManager,ActivityManager,wathdog等等,具体信息如下
Name: watchdog
Tgid: 1756 //线程组号=system_server PID
Pid: 1856 //线程ID
PPid: 1483 //父进程ID = zygote PID
TracerPid: 0 //接收跟踪该进程信息的进程ID = 没有?
10. 如果kill -9 1856, 会导致svcinfo_death@frameworks/base/cmds/servicemanager/service_manager.c,也就是所有注册到svclist的service都将died. kill掉任何一个system_server启动的thread 会导致system_server也被kill? 并会最终有如下log,
I/Zygote ( 1483): Exit zygote because system server (1756) has terminated 是从哪来的???????? sigchldHandler@dalvik/vm/native/dalvik_system_zygote.c
另外需要分析 zygote是如何exit的?????System.exit(?)。 需要提前说明的一点是Zygote 与 SystemServer 关系非常紧密!!
首先要分析zygote如何启动?和如何重启? zygote是运行在JVM空间的
a. init.rc 中有
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /proc/sysrq-trigger c
b. service zygote在frameworks/base/cmds/app_process/app_main.cpp--> main启动; runtime.start("com.android.internal.os.ZygoteInit",startSystemServer)@frameworks/base/core/jni/androidruntime.cpp 启动起来
c. androidruntime 会启动main@@frameworks/base/core/java/com/android/internal/os/zygoteinit.java, -->startSystemServer();--> pid = Zygote.forkSystemServer,其中forkSystemServer对应的jni函数是Dalvik_dalvik_system_Zygote_forkSystemServer@dalvik/vm/native/dalvik_system_zygote.c
d. forkAndSpecializeCommon@dalvik/vm/native/dalvik_system_zygote.c 很关键,fork一个子进程用于systemserver,并且还通过setSignalHandler();监控子进程的状态,
sa.sa_handler = sigchldHandler; //处理子进程终止的callback函数
err = sigaction (SIGCHLD, &sa, NULL); //注册 监听该子进程,如果子进程终止,将报告该信息给其父进程
e. 当子进程终止时,sigchldHandler会被触发 pid = waitpid(-1, &status, WNOHANG) 会读取当前终止的子进程的信息,并把其彻底销毁,然乎返回其PID;另外提一句,如果还发现其他的僵尸进程还一并把它给处理了。
f. 在sigchldHandler还有如下内容
if (pid == gDvm.systemServerPid) { //判断被终止的Process ID 是否是system server ID(即system_server 进程)
LOG(LOG_INFO, ZYGOTE_LOG_TAG,
"Exit zygote because system server (%d) has terminated\n",
(int) pid);
kill(getpid(), SIGKILL); //如果是,则把其父进程(即,zygote)也kill掉,如此可见system_server和zygote关系之紧密,誓死共存亡!!!
}
g. zygote 被kill掉后,会被init demon进程马上发现,并重启zygote进程,由此android系统就通过重启,解除了死锁。
13. 所有在init.rc中的service process的父进程ID=1 (init process), 并且这些process都只是运行在native世界中,还不是JVM.
14. 小结:SW watchdog实现机制很有意思,首先是通过java的synchronized 机制,来监控关键的三个service; system_server进程会启动所有的java services,当然包含那三个关键服务,还有watchdog thread 等线程;一旦watchdog发现死锁,会通过System.exit(10) kill掉自己的父进程(system_server);而一旦system_server被kill,它的的父进程zygote会监控到,马上把自己也干掉了,system_server不活zygote活着也就没有意义了;最后zygote把自己干掉了,会被init demon进程发现,重新启动android的所有java process,到此为止android系统又活过来了;但是init.rc中 在重启servie zygote 时还会执行onrestart write /proc/sysrq-trigger c, 郁闷!难道又手动让kernel也crash? 启动ramdump机制?最后整个手机都重启了!!!SW watchdog的意义何在? 上网查了下,增加onrestart write /proc/sysrq-trigger c, 为本公司特色!!这样处理真是一了百了。