Android 之 zygote 與程式建立

yangxi_001發表於2013-11-15

在android中,應用程式的入口是ActivityThead中的main函式,那麼之後系統是怎樣為應用程式建立程式的呢?SystemService又是怎樣建立的?答案是:zygote

zygote翻譯成中文是受精卵的意思,名字比較奇怪、但是很有意思。在android中,大部分的應用程式程式都是由zygote來建立的,為什麼用大部分,因為還有一些程式比如系統引導程式、init程式等不是有zygote建立的。相反,zygote還是在init程式之後才被建立的。在android中提到zygote,主要兩塊,一個是C/C++編寫的zygote,主要用來為應用和SystemService fork程式的。一個是java編寫的zygote介面,負責為應用和service呼叫C/C++ zygote的介面執行fork,從而建立VM程式。說明:在android中,service主要有NativeService和SystemService。SystemService主要是指系統中service,比如,InputMethodService、ActivityManagerService等。

zygote在android中主要有兩個作用:

建立執行時環境並啟動虛擬機器,執行com.android.internal.os.ZygoteInit的main函式,從而fork SystemService

[java] view plaincopy
  1. runtime.start("com.android.internal.os.ZygoteInit", startSystemServer);  

為應用程式建立DVM程式。

啟動SystemServer:

我們來看看zygote是怎樣建立SystemService程式的。在../base/cmds/app_process/app_main.cpp的主函式中,有這樣一段程式碼,它執行了

runtime.start("com.android.internal.os.ZygoteInit", startSystemServer);   //runtime繼承自AndroidRuntime

也就是說,在主函式中,初始化了執行時環境,並且建立虛擬機器,然後執行再com.android.internal.os.ZygoteInit的main函式

再來看看com.android.internal.os.ZygoteInit的main中都做了哪些事情。在看ZygoteInit之前,有必要先來看下相關的類,類圖如下:

 

在ZygoteInit的main函式中,主要執行了:

[java] view plaincopy
  1. registerZygoteSocket();//登記Listen埠  
  2. startSystemServer();//啟動SystemServer  

startSystemServer()呼叫Zygote的native方法 forkSystemServer(); 到這裡,java端的Zygote的準備工作就結束了,接下來就交給C/C++端的Zygote來執行fork任務了。來看下程式碼:

在 ../dalvik/vm/native/dalvik_system_Zygote.c 中

[java] view plaincopy
  1. static void Dalvik_dalvik_system_Zygote_forkSystemServer(  
  2. const u4* args, JValue* pResult)  
  3. {  
  4.     pid_t pid;  
  5.     /*呼叫forkAndSpecializeCommon,執行fork  */  
  6.     pid = forkAndSpecializeCommon(args, true);  
  7.     /* 檢查fork後返回的程式pid */  
  8.     if (pid > 0) {  
  9.         int status;  
  10.         LOGI("System server process %d has been created", pid);  
  11.         gDvm.systemServerPid = pid;  
  12.         if (waitpid(pid, &status, WNOHANG) == pid) {  
  13.             LOGE("System server process %d has died. Restarting Zygote!", pid);  
  14.             kill(getpid(), SIGKILL);  
  15.         }  
  16.     }  
  17.     RETURN_INT(pid);  
  18. }  

在這個裡面的fork程式主要是使用linux的fork程式。

經過這樣的過程SystemServer程式就建立起來了。android中的所有服務迴圈框架都是建立咋SystemServer上,接下來在SystemServer上,就可以建立所有系統服務。可參看:SystemServer.main();

系統服務啟動後會呼叫ActivityManagerService的systemReady方法,並最終啟動HomeActivity。

啟動應用程式:

我們在上一篇介紹ActivityThread和ActivityManagerService時已經講過,程式的主入口是在ActivityThread的main函式,activity的startActivity最終是在ActivityManagerService中執行的,那麼應用程式的程式是怎麼建立的?看下類圖:

 

 

我們再來看看ActivityManagerService中的startProcessLocked方法。

[java] view plaincopy
  1. int pid = Process.start("android.app.ActivityThread",  
  2.                     mSimpleProcessManagement ? app.processName : null, uid, uid,  
  3.                     gids, debugFlags, null);  

通過Process的start方法來建立程式。

[java] view plaincopy
  1. / **  
  2.   *通過Zygote程式來建立新的vm程式  
  3.   */  
  4.   
  5.   public static final int start(final String processClass,final String niceName,int uid, int gid, int[] gids,int debugFlags,String[] zygoteArgs)  
  6.   {  
  7.       if (supportsProcesses()) {  
  8.           try {  
  9.               return startViaZygote(processClass, niceName, uid, gid, gids,  
  10.                       debugFlags, zygoteArgs);     //argsForZygote.add("--runtime-init")初始化執行環境  
  11.           } catch (ZygoteStartFailedEx ex) {  
  12.               Log.e(LOG_TAG,  
  13.                       "Starting VM process through Zygote failed");  
  14.               throw new RuntimeException(  
  15.                       "Starting VM process through Zygote failed", ex);  
  16.           }  
  17.   
  18.       } else {  
  19.   
  20.           // Running in single-process mode  
  21.           Runnable runnable = new Runnable() {  
  22.                       public void run() {  
  23.                           Process.invokeStaticMain(processClass);  
  24.                       }  
  25.           };  
  26.           // Thread constructors must not be called with null names (see spec).  
  27.           if (niceName != null) {  
  28.               new Thread(runnable, niceName).start();  
  29.           } else {  
  30.               new Thread(runnable).start();  
  31.           }  
  32.           return 0;  
  33.       }  
  34.   }  

在ZygoteConnection中獲取套接字連線,並解析啟動引數。來看下runOnce方法:

 從LocalSocket. mSocket中解析引數

[java] view plaincopy
  1. try {  
  2.           args = readArgumentList();  
  3.           descriptors = mSocket.getAncillaryFileDescriptors();  
  4.       } catch (IOException ex) {  
  5.           Log.w(TAG, "IOException on command socket " + ex.getMessage());  
  6.           closeSocket();  
  7.           return true;  
  8.       }  

呼叫Zygote的native方法forkAndSpecialize,執行程式的建立工作。本地方法的實現也是在 ../dalvik/vm/native/dalvik_system_Zygote.c 中,底層呼叫linux的fork。

[java] view plaincopy
  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  2.   
  3.                     parsedArgs.gids, parsedArgs.debugFlags, rlimits);  

這樣應用程式的程式就建立起來了。從ActivityManagerService開始的時序圖如下:

 

總結:

在android中SystemService的啟動是在Zygote程式建立好後進行的,並且由Zygote程式建立好DVM執行環境,載入ZygoteInit的main函式,最終呼叫Zygote的本地方法forkSystemServer,並執行linux的fork方法建立SystemServer程式。應用程式的程式也是由Zygote建立的,在ActivityManagerService中的startProcessLocked中呼叫了Process.start()方法。並通過連線呼叫Zygote的native方法forkAndSpecialize,執行fork任務。應用程式和服務程式位於不同的程式中,他們之間是通過IPC進行資料傳遞的。接下來一篇會介紹在android中的程式間通訊機制:Binder

相關文章