Watchdog実現原理
転入先http://mp.weixin.qq.com/s/5kO8Hgdp1MrfJvaz7avcMg
1.Watchdog起動
前回の記事ではWatchdogの定義を簡単に紹介し、Watchdogがシステムの再起動を引き起こす問題の分析を一例で紹介し、Watchdogに対して感性的な認識を持たせた.本文はWatchdogの動作原理を紹介し、理性的な認識を持つことを目的としています.
まずWatchdogの主要メンバーのクラス継承関係を整理します.
WatchdogはThreadに継承され、実際にはsystem_で実行されています.serverプロセスのスレッドで、起動コード:
[frameworks/base/services/java/com/android/server/SystemServer.java] Watchdogクラスの実装はjavaでよく使われる単一のモードを採用している.getInstance()メソッドでクラスオブジェクトを構築します. Androidシステムの起動が完了するとmActivityManagerServicesが呼び出されます.SystemReady()メソッドは、start()を介してWatchdogスレッドを動作させます.
Watchdog構築方法:
[frameworks/base/services/core/java/com/android/server/Watchdog.java]
2.Watchdog動作原理
まずWatchdogの全体的なブロック図を見てみましょう.
FgThread,UiThread,IoThread,DisplayThreadはAndroidシステムで実現される特殊なスレッドであり、名前からだいたい の役割がわかる Looper.getMainLooper()は実はsystem_サーバこのプロセスのmain looperは、SystemServerのためです.JAvaにはLooperが呼び出されていますprepareMainLooper() 実際にWatchdogによって直接モニタリングされているのは、上記の5つのスレッドのlooperが正常かどうかであり、もちろんaddThread()によってモニタリングが必要なlooper も追加される. FgThreadスレッドのlooperはまた、AMS、PMSなどの重要なシステムサービスがデッドロックしているかどうかを監視する責任を負います.
AMSを例に、Watchdogがデッドロックかどうかを監視する方法を見てみましょう.まず、Activity Management Servicesを見てみましょう.JAvaクラスでは、どのような特殊な処理が行われていますか.
[frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java] AMSはWatchdogを継承する.Monitorこのインタフェース AMSでWatchdogを実現する.Monitorインタフェースのmonitor()メソッドは、1つのロック操作を実現するだけで addMonitor()メソッドにより、AMSをmMonitorCheckerというHandlerCheckerクラスオブジェクトに 追加する
Androidシステムの起動完了後、Watchdogスレッドが実行を開始し、Watchdogに入る.JAvaのrun()メソッド.
[frameworks/base/services/core/java/com/android/server/Watchdog.java] Watchdogスレッドのrun()メソッドでは、mHandlerCheckersの各HandlerCheckerオブジェクトのscheduleCheckLocked()メソッドを1回ずつ呼び出して、もちろんmMonitorChecker を含む CHECKを待つINTERVAL時間(CHECK_INTERVALは真のTIMEOUT時間の半分)を呼び出し、evaluateCheckerCompletionLocked()メソッドを呼び出して試行操作後の結果を表示します.ここでは、すべてのHandlerCheckerオブジェクトの結果の中で最も遅れた値 を返します.試した結果WAITED_HALFでは、Activity Management Servicesが呼び出されます.dumpStackTraces()は、traceファイルにスタックを印刷し、次に、試行動作 を行う.で2番目のCHECK_INTERVAL時間後の戻り値がOVERDUEである場合、getBlockedCheckersLocked()およびdescribeCheckersLocked()メソッドによりblockされたlooperおよびmonitor情報が取得する、Process.killProcess(Process.myPid()殺しsystem_serverプロセス 2.1 hc.scheduleCheckLocked()
AMSはmonitorオブジェクトとしてmMonitorCheckerオブジェクトに存在するため、試行操作時にmHandlerが呼び出される.postAtFrontOfQueue(this)メソッドは、mMonitorCheckerのrun()メソッドの実行を待つ.
mMonitorsにはAMSがあるのでrun()メソッドではAMSのmonitorが呼び出されますが、前述したようにAMSのmonitor()メソッドは等持ロック操作synchronized(this){}であり、AMSにデッドロックが発生するとrun()メソッドは実行できず、mCompletedもtrueにはなりません.
ここでは、WatchdogがmMonitor Checkerが表すlooperを監視するほか、monitorがないスレッドlooperもあります(AndroidシステムのすべてのmonitorはmMonitor Checkerにあります).これらのlooperについては、この2つのコードを見ると、それらの試行操作は主にlooperのqueueがブロックされているかどうかを見ることによって判断され、queueがブロックされている場合、上記のrun()メソッドは実行できないことがわかります.
2.2 evaluateCheckerCompletionLocked()
evaluateCheckerCompletionLocked()メソッドの戻り値は、mHandlerCheckersセット内のすべてのHandlerCheckerオブジェクトの中で最もヒステリシスの状態値です.
HandlerCheckerオブジェクトの現在の状態値は、mCompletedの値を判断し、HandlerCheckerの待ち時間と組み合わせることによって決定される.
2.3タイムアウト後
Watchdogのデフォルトのタイムアウト時間は1分で、デッドロックやブロックが1分を超えるとWatchdogはタイムアウトとみなされます.この時はシステムを直接殺すのが普通ですサーバですが、再起動しない場合は2つあります debuggerWasConnected>0、つまりデバッガが接続され、システムは にデバッグされています. allowRestart=false、am hangコマンドでこの値 を変更できます.
3.まとめ
上はコードの面からWatchdogの原理を話して、もしあなたがコードがどのように実現したのかを理解したくないならば、それは上の内容を無視して、直接ここの結論を見ることができます. Watchdogは実際にはsystem_で実行されるスレッドですserverプロセスにおける Watchdogはスレッドのlooper状態を直接監視しているが、その中の1つのlooperはFgThreadスレッドの中にあり、そのHandlerCheckerを代表するmMonitorCheckerであり、システムにおける重要なシステムサービスの状態 を監視している. Watchdogではlooperのqueueとmonitorの状態を探り続け、1分以上応答しなければデッドロックが発生したと判断し、traceファイルにsystem_を印刷しますserverプロセスのスタック情報 デッドロックが発生した後、Watchdogはデバッガ接続があるかどうかと「am hang」を設定するかどうかによってsystemを殺すかどうかを決定します.server.
1.Watchdog起動
前回の記事ではWatchdogの定義を簡単に紹介し、Watchdogがシステムの再起動を引き起こす問題の分析を一例で紹介し、Watchdogに対して感性的な認識を持たせた.本文はWatchdogの動作原理を紹介し、理性的な認識を持つことを目的としています.
まずWatchdogの主要メンバーのクラス継承関係を整理します.
WatchdogはThreadに継承され、実際にはsystem_で実行されています.serverプロセスのスレッドで、起動コード:
[frameworks/base/services/java/com/android/server/SystemServer.java]
private void startOtherServices() {
... ...
final Watchdog watchdog = Watchdog.getInstance();
watchdog.init(context, mActivityManagerService);
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
... ...
// Watchdog
Watchdog.getInstance().start();
... ...
}
}
... ...
}
Watchdog構築方法:
[frameworks/base/services/core/java/com/android/server/Watchdog.java]
private Watchdog() {
mMonitorChecker = new HandlerChecker(FgThread.getHandler(),
"foreground thread", DEFAULT_TIMEOUT);
mHandlerCheckers.add(mMonitorChecker);
mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()),
"main thread", DEFAULT_TIMEOUT));
mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(),
"ui thread", DEFAULT_TIMEOUT));
mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),
"i/o thread", DEFAULT_TIMEOUT));
mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
"display thread", DEFAULT_TIMEOUT));
addMonitor(new BinderThreadMonitor());
}
2.Watchdog動作原理
まずWatchdogの全体的なブロック図を見てみましょう.
AMSを例に、Watchdogがデッドロックかどうかを監視する方法を見てみましょう.まず、Activity Management Servicesを見てみましょう.JAvaクラスでは、どのような特殊な処理が行われていますか.
[frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java]
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
... ...
public ActivityManagerService(Context systemContext) {
... ...
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
... ...
}
public void monitor() {
synchronized (this) { }
}
... ...
}
Androidシステムの起動完了後、Watchdogスレッドが実行を開始し、Watchdogに入る.JAvaのrun()メソッド.
[frameworks/base/services/core/java/com/android/server/Watchdog.java]
public void run() {
while(true) {
long timeout = CHECK_INTERVAL;
for (int i=0; i
while (timeout > 0) {
wait(timeout);
}
final int waitState = evaluateCheckerCompletionLocked();
if (waitState == COMPLETED) {
waitedHalf = false;
continue;
} else if (waitState == WAITING) {
continue;
} else if (waitState == WAITED_HALF) {
if (!waitedHalf) {
ArrayList pids = new ArrayList();
pids.add(Process.myPid());
ActivityManagerService.dumpStackTraces(true, pids, null, null,
NATIVE_STACKS_OF_INTEREST);
waitedHalf = true;
}
continue;
}
blockedCheckers = getBlockedCheckersLocked();
subject = describeCheckersLocked(blockedCheckers);
if (debuggerWasConnected >= 2) {
Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
} else if (debuggerWasConnected > 0) {
Slog.w(TAG, "Debugger was connected: Watchdog is *not* killing the system process");
} else if (!allowRestart) {
Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process");
} else {
Process.killProcess(Process.myPid());
}
}
}
public void scheduleCheckLocked() {
if (mMonitors.size() == 0 &&
mHandler.getLooper().getQueue().isPolling()) {
mCompleted = true;
return;
}
if (!mCompleted) {
return;
}
mCompleted = false;
mCurrentMonitor = null;
mStartTime = SystemClock.uptimeMillis();
mHandler.postAtFrontOfQueue(this);
}
AMSはmonitorオブジェクトとしてmMonitorCheckerオブジェクトに存在するため、試行操作時にmHandlerが呼び出される.postAtFrontOfQueue(this)メソッドは、mMonitorCheckerのrun()メソッドの実行を待つ.
public void run() {
final int size = mMonitors.size();
for (int i = 0 ; i < size ; i++) {
synchronized (Watchdog.this) {
mCurrentMonitor = mMonitors.get(i);
}
mCurrentMonitor.monitor();
}
synchronized (Watchdog.this) {
mCompleted = true;
mCurrentMonitor = null;
}
}
mMonitorsにはAMSがあるのでrun()メソッドではAMSのmonitorが呼び出されますが、前述したようにAMSのmonitor()メソッドは等持ロック操作synchronized(this){}であり、AMSにデッドロックが発生するとrun()メソッドは実行できず、mCompletedもtrueにはなりません.
ここでは、WatchdogがmMonitor Checkerが表すlooperを監視するほか、monitorがないスレッドlooperもあります(AndroidシステムのすべてのmonitorはmMonitor Checkerにあります).これらのlooperについては、この2つのコードを見ると、それらの試行操作は主にlooperのqueueがブロックされているかどうかを見ることによって判断され、queueがブロックされている場合、上記のrun()メソッドは実行できないことがわかります.
2.2 evaluateCheckerCompletionLocked()
private int evaluateCheckerCompletionLocked() {
int state = COMPLETED;
for (int i=0; i return state;
}
evaluateCheckerCompletionLocked()メソッドの戻り値は、mHandlerCheckersセット内のすべてのHandlerCheckerオブジェクトの中で最もヒステリシスの状態値です.
public int getCompletionStateLocked() {
if (mCompleted) {
return COMPLETED;
} else {
long latency = SystemClock.uptimeMillis() - mStartTime;
if (latency < mWaitMax/2) {
return WAITING;
} else if (latency < mWaitMax) {
return WAITED_HALF;
}
}
return OVERDUE;
}
HandlerCheckerオブジェクトの現在の状態値は、mCompletedの値を判断し、HandlerCheckerの待ち時間と組み合わせることによって決定される.
2.3タイムアウト後
Watchdogのデフォルトのタイムアウト時間は1分で、デッドロックやブロックが1分を超えるとWatchdogはタイムアウトとみなされます.この時はシステムを直接殺すのが普通ですサーバですが、再起動しない場合は2つあります
3.まとめ
上はコードの面からWatchdogの原理を話して、もしあなたがコードがどのように実現したのかを理解したくないならば、それは上の内容を無視して、直接ここの結論を見ることができます.