自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Watchdog機制源碼分析

移動開發(fā) Android
Android設計了一個軟件層面Watchdog,用于保護一些重要的系統(tǒng)服務,當出現(xiàn)故障時,通常會讓Android系統(tǒng)重啟,由于這種機制的存在,就經(jīng)常會出現(xiàn)一些system_server進程被Watchdog殺掉而發(fā)生手機重啟的問題.

[[434595]]

前言

Linux引入Watchdog,在Linux內核下,當Watchdog啟動后,便設定了一個定時器,如果在超時時間內沒有對/dev/Watchdog進行寫操作,則會導致系統(tǒng)重啟。通過定時器實現(xiàn)的Watchdog屬于軟件層面;

Android設計了一個軟件層面Watchdog,用于保護一些重要的系統(tǒng)服務,當出現(xiàn)故障時,通常會讓Android系統(tǒng)重啟,由于這種機制的存在,就經(jīng)常會出現(xiàn)一些system_server進程被Watchdog殺掉而發(fā)生手機重啟的問題;

今天我們就來分析下原理;

一、WatchDog啟動機制詳解

ANR機制是針對應用的,對于系統(tǒng)進程來說,如果長時間“無響應”,Android系統(tǒng)設計了WatchDog機制來管控。如果超過了“無響應”的延時,那么系統(tǒng)WatchDog會觸發(fā)自殺機制;

Watchdog是一個線程,繼承于Thread,在SystemServer.java里面通過getInstance獲取watchdog的對象;

1、在SystemServer.java中啟動

  1. private void startOtherServices() { 
  2.     ······ 
  3.     traceBeginAndSlog("InitWatchdog"); 
  4.     final Watchdog watchdog = Watchdog.getInstance(); 
  5.     watchdog.init(context, mActivityManagerService); 
  6.     traceEnd(); 
  7.     ······ 
  8.     traceBeginAndSlog("StartWatchdog"); 
  9.     Watchdog.getInstance().start(); 
  10.    traceEnd(); 

因為是線程,所以,只要start即可;

2、查看WatchDog的構造方法

  1. private Watchdog() { 
  2.         super("watchdog"); 
  3.         // Initialize handler checkers for each common thread we want to check.  Note 
  4.         // that we are not currently checking the background thread, since it can 
  5.         // potentially hold longer running operations with no guarantees about the timeliness 
  6.         // of operations there. 
  7.         // The shared foreground thread is the main checker.  It is where we 
  8.         // will also dispatch monitor checks and do other work
  9.         mMonitorChecker = new HandlerChecker(FgThread.getHandler(), 
  10.                 "foreground thread", DEFAULT_TIMEOUT); 
  11.         mHandlerCheckers.add(mMonitorChecker); 
  12.         // Add checker for main thread.  We only do a quick check since there 
  13.         // can be UI running on the thread. 
  14.         mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()), 
  15.                 "main thread", DEFAULT_TIMEOUT)); 
  16.         // Add checker for shared UI thread. 
  17.         mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(), 
  18.                 "ui thread", DEFAULT_TIMEOUT)); 
  19.         // And also check IO thread. 
  20.         mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(), 
  21.                 "i/o thread", DEFAULT_TIMEOUT)); 
  22.         // And the display thread. 
  23.         mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(), 
  24.                 "display thread", DEFAULT_TIMEOUT)); 
  25.         // Initialize monitor for Binder threads. 
  26.         addMonitor(new BinderThreadMonitor()); 
  27.         mOpenFdMonitor = OpenFdMonitor.create(); 
  28.         // See the notes on DEFAULT_TIMEOUT. 
  29.         assert DB || 
  30.                 DEFAULT_TIMEOUT > ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS; 
  31.         // mtk enhance 
  32.         exceptionHWT = new ExceptionLog(); 
  33.     } 

重點關注兩個對象:mMonitorChecker和mHandlerCheckers

mHandlerCheckers列表元素的來源:

構造對象的導入:UiThread、IoThread、DisplatyThread、FgThread加入

外部導入:Watchdog.getInstance().addThread(handler);

mMonitorChecker列表元素的來源:

外部導入:Watchdog.getInstance().addMonitor(monitor);

特別說明:addMonitor(new BinderThreadMonitor());

3、查看WatchDog的run方法

  1. public void run() { 
  2.         boolean waitedHalf = false
  3.         boolean mSFHang = false
  4.         while (true) { 
  5.             ······ 
  6.             synchronized (this) { 
  7.                 ······ 
  8.                 for (int i=0; i<mHandlerCheckers.size(); i++) { 
  9.                     HandlerChecker hc = mHandlerCheckers.get(i); 
  10.                     hc.scheduleCheckLocked(); 
  11.                 } 
  12.                 ······ 
  13.             } 
  14.             ······ 

對mHandlerCheckers列表元素進行檢測;

4、查看HandlerChecker的scheduleCheckLocked

  1. public void scheduleCheckLocked() { 
  2.         if (mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling()) { 
  3.                 // If the target looper has recently been polling, then 
  4.                 // there is no reason to enqueue our checker on it since that 
  5.                 // is as good as it not being deadlocked.  This avoid having 
  6.                 // to do a context switch to check the thread.  Note that we 
  7.                 // only do this if mCheckReboot is false and we have no 
  8.                 // monitors, since those would need to be executed at this point. 
  9.                 mCompleted = true
  10.                 return
  11.         } 
  12.         if (!mCompleted) { 
  13.                 // we already have a check in flight, so no need 
  14.                 return
  15.         } 
  16.         mCompleted = false
  17.         mCurrentMonitor = null
  18.         mStartTime = SystemClock.uptimeMillis(); 
  19.         mHandler.postAtFrontOfQueue(this); 

mMonitors.size() == 0的情況:主要為了檢查mHandlerCheckers中的元素是否超時,運用的手段:mHandler.getLooper().getQueue().isPolling();

mMonitorChecker對象的列表元素一定是大于0,此時,關注點在mHandler.postAtFrontOfQueue(this);

  1. public void run() { 
  2.        final int size = mMonitors.size(); 
  3.        for (int i = 0 ; i < size ; i++) { 
  4.             synchronized (Watchdog.this) { 
  5.                 mCurrentMonitor = mMonitors.get(i); 
  6.             } 
  7.             mCurrentMonitor.monitor(); 
  8.        } 
  9.        synchronized (Watchdog.this) { 
  10.             mCompleted = true
  11.             mCurrentMonitor = null
  12.        } 

監(jiān)聽monitor方法,這里是對mMonitors進行monitor,而能夠滿足條件的只有:mMonitorChecker,例如:各種服務通過addMonitor加入列表;

  1. ActivityManagerService.java 
  2.     Watchdog.getInstance().addMonitor(this);  
  3. InputManagerService.java 
  4.     Watchdog.getInstance().addMonitor(this);  
  5. PowerManagerService.java 
  6.     Watchdog.getInstance().addMonitor(this);  
  7. ActivityManagerService.java 
  8.     Watchdog.getInstance().addMonitor(this);  
  9. WindowManagerService.java 
  10.     Watchdog.getInstance().addMonitor(this); 

而被執(zhí)行的monitor方法很簡單,例如ActivityManagerService:

  1. public void monitor() { 
  2.      synchronized (this) { } 

這里僅僅是檢查系統(tǒng)服務是否被鎖住;

Watchdog的內部類;

  1. private static final class BinderThreadMonitor implements Watchdog.Monitor { 
  2.         @Override 
  3.         public void monitor() { 
  4.             Binder.blockUntilThreadAvailable(); 
  5.         } 
  6. android.os.Binder.java 
  7. public static final native void blockUntilThreadAvailable(); 
  8. android_util_Binder.cpp 
  9. static void android_os_Binder_blockUntilThreadAvailable(JNIEnv* env, jobject clazz) 
  10.     return IPCThreadState::self()->blockUntilThreadAvailable(); 
  11. IPCThreadState.cpp 
  12. void IPCThreadState::blockUntilThreadAvailable() 
  13.     pthread_mutex_lock(&mProcess->mThreadCountLock); 
  14.     while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) { 
  15.         ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%lu mMaxThreads=%lu\n"
  16.                 static_cast<unsigned long>(mProcess->mExecutingThreadsCount), 
  17.                 static_cast<unsigned long>(mProcess->mMaxThreads)); 
  18.         pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock); 
  19.     } 
  20.     pthread_mutex_unlock(&mProcess->mThreadCountLock); 

這里僅僅是檢查進程中包含的可執(zhí)行線程的數(shù)量不能超過mMaxThreads,如果超過了最大值(31個),就需要等待;

  1. ProcessState.cpp 
  2. #define DEFAULT_MAX_BINDER_THREADS 15 
  3. 但是systemserver.java進行了設置 
  4. // maximum number of binder threads used for system_server 
  5. // will be higher than the system default 
  6. private static final int sMaxBinderThreads = 31; 
  7. private void run() { 
  8.     ······ 
  9.     BinderInternal.setMaxThreads(sMaxBinderThreads); 
  10.     ······ 

5、發(fā)生超時后退出

  1. public void run() { 
  2.     ······ 
  3.     Process.killProcess(Process.myPid()); 
  4.     System.exit(10); 
  5.     ······ 

kill自己所在進程(system_server),并退出;

二、原理解釋

1、系統(tǒng)中所有需要監(jiān)控的服務都調用Watchdog的addMonitor添加Monitor Checker到mMonitors這個List中或者addThread方法添加Looper Checker到mHandlerCheckers這個List中;

2、當Watchdog線程啟動后,便開始無限循環(huán),它的run方法就開始執(zhí)行;

  • 第一步調用HandlerChecker#scheduleCheckLocked處理所有的mHandlerCheckers
  • 第二步定期檢查是否超時,每一次檢查的間隔時間由CHECK_INTERVAL常量設定,為30秒,每一次檢查都會調用evaluateCheckerCompletionLocked()方法來評估一下HandlerChecker的完成狀態(tài):
  • COMPLETED表示已經(jīng)完成;
  • WAITING和WAITED_HALF表示還在等待,但未超時,WAITED_HALF時候會dump一次trace.
  • OVERDUE表示已經(jīng)超時。默認情況下,timeout是1分鐘;

3、如果超時時間到了,還有HandlerChecker處于未完成的狀態(tài)(OVERDUE),則通過getBlockedCheckersLocked()方法,獲取阻塞的HandlerChecker,生成一些描述信息,保存日志,包括一些運行時的堆棧信息。

4、最后殺死SystemServer進程;

總結

Watchdog是一個線程,用來監(jiān)聽系統(tǒng)各項服務是否正常運行,沒有發(fā)生死鎖;

HandlerChecker用來檢查Handler以及monitor;

monitor通過鎖來判斷是否死鎖;

超時30秒會輸出log,超時60秒會重啟;

Watchdog會殺掉自己的進程,也就是此時system_server進程id會變化;

本文轉載自微信公眾號「Android開發(fā)編程」

 

責任編輯:姜華 來源: Android開發(fā)編程
相關推薦

2012-05-31 02:54:07

HadoopJava

2021-12-06 14:52:08

動畫Android補間動畫

2024-08-30 10:40:12

2023-08-28 07:49:24

Redisson鎖機制源碼

2020-05-26 18:50:46

JVMAttachJava

2021-03-16 21:45:59

Python Resize機制

2023-06-15 14:09:00

解析器Servlet容器

2014-08-26 11:11:57

AsyncHttpCl源碼分析

2011-03-15 11:33:18

iptables

2011-06-23 13:10:39

Python 對象機制

2024-09-06 09:37:45

WebApp類加載器Web 應用

2011-05-26 10:05:48

MongoDB

2023-10-31 16:00:51

類加載機制Java

2014-07-18 11:11:16

SEAndroid

2011-08-24 16:59:59

LuaModule

2021-08-12 16:28:10

AndroidHandleLooper

2011-05-26 16:18:51

Mongodb

2011-06-23 14:40:13

Qt 信號

2017-01-16 15:05:17

Linux信號機制分析

2009-06-18 14:51:12

Hibernate緩存Hibernate
點贊
收藏

51CTO技術棧公眾號