Zygote啓動及其做用

目錄java

一、Zygote簡介android

二、Zygote進程如何啓動ios

  2.1 init.zygote64_32.rc文件服務器

  2.2 查看ps信息app

  2.3 啓動框架

三、Zygote做用socket

  3.1 啓動system_server函數

  3.2 查看與驗證Zygote啓動systemserveroop

  3.3 Zygote啓動其餘子進程post

四、總結

 

一、Zygote簡介

  • 1.1 系統啓動流程
    • 從按下電源到看到launcher,手機的啓動是一個很是複雜的過程。

      bootloader是手機上電以後第一個運行的程序,其做用是硬件的初始化,其做用相似於PC機的bios。

      bootloader完成其工做後,將 Linux kernel鏡像拷貝到內存中。完成剩餘的與硬件平臺相關的初始化工做,好比文件系統,驅動模塊。最後啓動第一個用戶進程-init 進程並等待用戶進程的執行。

      用戶空間的第一個進程init
  • 1.2 zygote理解
    • 在Android系統中,全部的應用程序進程以及系統服務進程SystemServer都是由Zygote進程孕育(fork)出來的。因爲Zygote進程在Android系統中有着如此重要的地位,本文將詳細分析它的啓動過程。---老羅
    • android系統中建立java世界的盤古  建立新進程的女媧。 ---鄧凡平

二、Zygote進程如何啓動

  • 2.1 init.zygote64_32.rc文件
    • system/core/rootdir/init.zygote64_32.rc文件內容
    • 複製代碼
       1 service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
       2     class main
       3     socket zygote stream 660 root system
       4     onrestart write /sys/android_power/request_state wake
       5     onrestart write /sys/power/state on
       6     onrestart restart media
       7     onrestart restart netd
       8 
       9 service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
      10     class main
      11     socket zygote_secondary stream 660 root system
      12     onrestart restart zygote
      複製代碼

       

  • 2.2 查看ps信息
    • Zygote6四、Zygote是在init.rc中定義的服務進程,由init進程啓動,PPID均爲1。其中比較關鍵的vold、rild、surfaceflinger等關鍵進程也都是經過init進程啓動的。

    • LOCAL_MULTILIB: Android.mk中用來設置編譯爲32位或者64位的apk,so等

  • 2.3 啓動
    • Zygote process main(frameworks/base/cmds/app_process/app_main.cpp)
    • 複製代碼
        1 int main(int argc, char* const argv[])
        2 {
        3     ...
      121     if (zygote) {
      122         runtime.start("com.android.internal.os.ZygoteInit", args);
      123     } else if (className) {
      124         runtime.start("com.android.internal.os.RuntimeInit", args);
      125     } else {
      126         fprintf(stderr, "Error: no class name or --zygote supplied.\n");
      127         app_usage();
      128         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
      129         return 10;
      130     }
      131 }
      複製代碼

       

    • 將init.rc中指定的-Xzygote參數傳給JVM
      將進程的名字改成zygote(能夠回答前面的問題)
      執行AppRuntime類的start()方法,runtime.start(「com.android.internal.os.ZygoteInit」, true);
    • 複製代碼
        1 void AndroidRuntime::start(const char* className, const Vector<String8>& options)
        2 {
        3     ... 
       30     //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
       31     //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
       32 
       33     /* start the virtual machine */
       34     JniInvocation jni_invocation;
       35     jni_invocation.Init(NULL);
       36     JNIEnv* env;
       37     if (startVm(&mJavaVM, &env) != 0) {
       38         return;
       39     }
       40     onVmCreated(env);
       41 
       42     /*
       43      * Register android functions.
       44      */
       45     if (startReg(env) < 0) {
       46         ALOGE("Unable to register all android natives\n");
       47         return;
       48     }
       49 
       50     /*
       51      * We want to call main() with a String array with arguments in it.
       52      * At present we have two arguments, the class name and an option string.
       53      * Create an array to hold them.
       54      */
       55     jclass stringClass;
       56     jobjectArray strArray;
       57     jstring classNameStr;
       58 
       59     stringClass = env->FindClass("java/lang/String");
       60     assert(stringClass != NULL);
       61     strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
       62     assert(strArray != NULL);
       63     classNameStr = env->NewStringUTF(className);
       64     assert(classNameStr != NULL);
       65     env->SetObjectArrayElement(strArray, 0, classNameStr);
       66 
       67     for (size_t i = 0; i < options.size(); ++i) {
       68         jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
       69         assert(optionsStr != NULL);
       70         env->SetObjectArrayElement(strArray, i + 1, optionsStr);
       71     }
       72 
       73     /*
       74      * Start VM.  This thread becomes the main thread of the VM, and will
       75      * not return until the VM exits.
       76      */
       77     char* slashClassName = toSlashClassName(className);
       78     jclass startClass = env->FindClass(slashClassName);
       79     if (startClass == NULL) {
       80         ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
       81         /* keep going */
       82     } else {
       83         jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
       84             "([Ljava/lang/String;)V");
       85         if (startMeth == NULL) {
       86             ALOGE("JavaVM unable to find main() in '%s'\n", className);
       87             /* keep going */
       88         } else {
       89             env->CallStaticVoidMethod(startClass, startMeth, strArray);
       90 
       91 #if 0
       92             if (env->ExceptionCheck())
       93                 threadExitUncaughtException(env);
       94 #endif
       95         }
       96     }
       97     free(slashClassName);
       98 
       99     ALOGD("Shutting down VM\n");
      100     if (mJavaVM->DetachCurrentThread() != JNI_OK)
      101         ALOGW("Warning: unable to detach main thread\n");
      102     if (mJavaVM->DestroyJavaVM() != 0)
      103         ALOGW("Warning: VM did not shut down cleanly\n");
      104 }
      複製代碼

       

    • runtime.start函數,即在frameworks\base\core\jni\AndroidRuntime.cpp文件中
      • AndroidRuntime::startVm()中,設置一些虛擬機的參數後,經過JNI_CreateJavaVM()啓動虛擬機。
      • StartReg()註冊JNI 函數
      • env->CallStaticVoidMethod,調用ZygoteInit類的main()方法,正式進入到Java世界.
    • frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    • 複製代碼
      public static void main(String argv[]) {
              try {
                  ....
                  registerZygoteSocket(socketName);
                  EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                      SystemClock.uptimeMillis());
                  preload();
                  EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                      SystemClock.uptimeMillis());
      
                  // Finish profiling the zygote initialization.
                  SamplingProfilerIntegration.writeZygoteSnapshot();
      
                  // Do an initial gc to clean up after startup
                  gc();
      
                  // Disable tracing so that forked processes do not inherit stale tracing tags from
                  // Zygote.
                  Trace.setTracingEnabled(false);
      
                  if (startSystemServer) {
                      startSystemServer(abiList, socketName);
                  }
      
                  Log.i(TAG, "Accepting command socket connections");
                  runSelectLoop(abiList);
      
                  closeServerSocket();
              } catch (MethodAndArgsCaller caller) {
                  caller.run();
              } catch (RuntimeException ex) {
                  Log.e(TAG, "Zygote died with exception", ex);
                  closeServerSocket();
                  throw ex;
              }
          }
      複製代碼

       

    • registerZygoteSocket,建立Socket服務端對象sServerSocket

      preload方法預加載類,資源等

      調用startSystemServer方法啓動系統服務system_server

      runSelectLoopMode監聽和處理sServerSocket的Socket請求

  • 三、Zygote做用
    • 3.1 啓動system_server
      • 複製代碼
         1 /**
         2      * Prepare the arguments and fork for the system server process.
         3      */
         4     private static boolean startSystemServer(String abiList, String socketName)
         5             throws MethodAndArgsCaller, RuntimeException {
         6        ...
        31         int pid;
        32 
        33         try {
        34             parsedArgs = new ZygoteConnection.Arguments(args);
        35             ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        36             ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
        37 
        38             /* Request to fork the system server process */
        39             pid = Zygote.forkSystemServer(
        40                     parsedArgs.uid, parsedArgs.gid,
        41                     parsedArgs.gids,
        42                     parsedArgs.debugFlags,
        43                     null,
        44                     parsedArgs.permittedCapabilities,
        45                     parsedArgs.effectiveCapabilities);
        46         } catch (IllegalArgumentException ex) {
        47             throw new RuntimeException(ex);
        48         }
        49 
        50         /* For child process */
        51         if (pid == 0) {//子進程進入
        52             if (hasSecondZygote(abiList)) {
        53                 waitForSecondaryZygote(socketName);
        54             }
        55 
        56             handleSystemServerProcess(parsedArgs);
        57         }
        58 
        59         return true;
        60     }
        複製代碼
      • forkSystemServer,調用Native方法fork子進程
        經過forkSystemServer方法返回的值,進入兩個分支處理:父進程返回子進程pid值,進入到ZygoteInit類中的main方法繼續處理;而子進程調用handleSystemServerProcess方法,最終會運行system_server。
      • 複製代碼
         1 /**
         2      * Finish remaining work for the newly forked system server process.
         3      */
         4     private static void handleSystemServerProcess(
         5             ZygoteConnection.Arguments parsedArgs)
         6             throws ZygoteInit.MethodAndArgsCaller {
         7 
         8         closeServerSocket();//子進程已經不是服務器了,因此關掉。
         9 
        10         // set umask to 0077 so new files and directories will default to owner-only permissions.
        11         Os.umask(S_IRWXG | S_IRWXO);
        12 
        13         if (parsedArgs.niceName != null) {
        14             Process.setArgV0(parsedArgs.niceName);
        15         }
        16 
        17         final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        18         if (systemServerClasspath != null) {
        19             performSystemServerDexOpt(systemServerClasspath);
        20         }
        21 
        22         if (parsedArgs.invokeWith != null) {
        23             String[] args = parsedArgs.remainingArgs;
        24             // If we have a non-null system server class path, we'll have to duplicate the
        25             // existing arguments and append the classpath to it. ART will handle the classpath
        26             // correctly when we exec a new process.
        27             if (systemServerClasspath != null) {
        28                 String[] amendedArgs = new String[args.length + 2];
        29                 amendedArgs[0] = "-cp";
        30                 amendedArgs[1] = systemServerClasspath;
        31                 System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
        32             }
        33 
        34             WrapperInit.execApplication(parsedArgs.invokeWith,
        35                     parsedArgs.niceName, parsedArgs.targetSdkVersion,
        36                     null, args);
        37         } else {
        38             ClassLoader cl = null;
        39             if (systemServerClasspath != null) {
        40                 cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
        41                 Thread.currentThread().setContextClassLoader(cl);
        42             }
        43 
        44             /*
        45              * Pass the remaining arguments to SystemServer.
        46              */
        47             RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        48         }
        49 
        50         /* should never reach here */
        51     }
        複製代碼

         

      • frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
      • 複製代碼
        43 public class RuntimeInit {
         44     。。。
        197     private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        198             throws ZygoteInit.MethodAndArgsCaller {
        199        。。。
        232        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
        233     }
        267     public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        268             throws ZygoteInit.MethodAndArgsCaller {
        269         if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
        270 
        271         redirectLogStreams();
        272 
        273         commonInit();
        274         nativeZygoteInit();
        275 
        276         applicationInit(targetSdkVersion, argv, classLoader);
        277     }
        297     private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        298             throws ZygoteInit.MethodAndArgsCaller {
        299         。。。
        308         VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        309         VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        310 
        311         。。。
        320         // Remaining arguments are passed to the start class's static main
        321         invokeStaticMain(args.startClass, args.startArgs, classLoader);
        322     }
        363     public static final IBinder getApplicationObject() {
        364         return mApplicationObject;
        365     }
        425 }
        複製代碼

         

      • 複製代碼
         1 public static void main(String argv[]) {
         2         try {
         3             。。。
        42             if (startSystemServer) {
        43                 startSystemServer(abiList, socketName);
        44             }
        45             。。。//然而並無機會進入循環
        50 } catch (MethodAndArgsCaller caller) { 51 caller.run(); 52 } catch (RuntimeException ex) { 53 Log.e(TAG, "Zygote died with exception", ex); 54 closeServerSocket(); 55 throw ex; 56 } 57 }
        複製代碼

         

      • 這個函數會執行兩個操做,一個是調用zygoteInitNative函數來執行一個Binder進程間通訊機制的初始化工做,這個工做完成以後,這個進 程中的Binder對象就能夠方便地進行進程間通訊了,另外一個是調用上面傳進來的com.android.server.SystemServer類的main函數。
    • 3.2 查看與驗證Zygote啓動systemserver
      • ps進程信息,驗證system_server是Zygote的分裂出的第一個子進程.
    • 3.3 Zygote啓動其餘子進程
      • 注意:重複的再也不涉及,咱們只是分析一下7-12吧。
      • frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
      • 複製代碼
         1 /**
         2      * Runs the zygote process's select loop. Accepts new connections as
         3      * they happen, and reads commands from connections one spawn-request's
         4      * worth at a time.
         5      *
         6      * @throws MethodAndArgsCaller in a child process when a main() should
         7      * be executed.
         8      */
         9     private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        10         。。。
        18 while (true) { 19 。。。 38 try { 39 fdArray = fds.toArray(fdArray); 40 index = selectReadable(fdArray); 41 } catch (IOException ex) { 42 throw new RuntimeException("Error in select()", ex); 43 } 44 45 if (index < 0) { 46 throw new RuntimeException("Error in select()"); 47 } else if (index == 0) { 48 ZygoteConnection newPeer = acceptCommandPeer(abiList); 49 peers.add(newPeer); 50 fds.add(newPeer.getFileDescriptor()); 51 } else { 52 boolean done; 53 done = peers.get(index).runOnce(); 54 55 if (done) { 56 peers.remove(index); 57 fds.remove(index); 58 } 59 } 60 } 61 }
        複製代碼

         

      • runSelectLoopMode中while(true)循環,接收到Socket請求後,會fork出子進程,子進程調用handleChildProc方法,最終拋出RuntimeInit.invokeStaticMain異常,退出while(true)循環(與fork Systemserver不同,後者沒有進入循環),進入到android.app.ActivityThread類的main方法執行;父進程調用handleParentProc方法,再次進入runSelectLoopMode中while(true)循環,準備接收下一個的請求事件。
      • frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
      • 複製代碼
          1 boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
                   ...
         37         try {
         38             ...
        105 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, 106 parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, 107 parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, 108 parsedArgs.appDataDir); 109 checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize"); 110 } catch (IOException ex) { 111 logAndPrintError(newStderr, "Exception creating pipe", ex); 112 } catch (ErrnoException ex) { 113 logAndPrintError(newStderr, "Exception creating pipe", ex); 114 } catch (IllegalArgumentException ex) { 115 logAndPrintError(newStderr, "Invalid zygote arguments", ex); 116 } catch (ZygoteSecurityException ex) { 117 logAndPrintError(newStderr, 118 "Zygote security policy prevents request: ", ex); 119 } 120 121 try { 122 if (pid == 0) { 123 // in child 124 IoUtils.closeQuietly(serverPipeFd); 125 serverPipeFd = null; 126 handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); 127 128 // should never get here, the child is expected to either 129 // throw ZygoteInit.MethodAndArgsCaller or exec(). 130 return true; 131 } else { 132 // in parent...pid of < 0 means failure 133 IoUtils.closeQuietly(childPipeFd); 134 childPipeFd = null; 135 return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); 136 } 137 } finally { 138 IoUtils.closeQuietly(childPipeFd); 139 IoUtils.closeQuietly(serverPipeFd); 140 } 141 }
        複製代碼

         

      • 10和11略過,只是返回而已。咱們如今進入子進程的handleChildProc。
      • 複製代碼
         1 private void handleChildProc(Arguments parsedArgs,
         2             FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
         3             throws ZygoteInit.MethodAndArgsCaller {
         4 
         5         /**
         6          * By the time we get here, the native code has closed the two actual Zygote
         7          * socket connections, and substituted /dev/null in their place.  The LocalSocket
         8          * objects still need to be closed properly.
         9          */
        10 
        11         closeSocket();
        12         ZygoteInit.closeServerSocket();
        13 
        14         。。。 
        55             if (parsedArgs.invokeWith != null) {
        56                 WrapperInit.execStandalone(parsedArgs.invokeWith,
        57                         parsedArgs.classpath, className, mainArgs);
        58             } else {
        59                 ClassLoader cloader;
        60                 if (parsedArgs.classpath != null) {
        61                     cloader = new PathClassLoader(parsedArgs.classpath,
        62                             ClassLoader.getSystemClassLoader());
        63                 } else {
        64                     cloader = ClassLoader.getSystemClassLoader();
        65                 }
        66 
        67                 try {
        68                     ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
        69                 } catch (RuntimeException ex) {
        70                     logAndPrintError(newStderr, "Error starting.", ex);
        71                 }
        72             }
        73         。。。
        74     }
        複製代碼
      • 剩餘的就和上面雷同了,這裏再也不分析。

四、總結

  • 系統啓動時init進程會建立Zygote進程,Zygote進程負責後續Android應用程序框架層的其它進程的建立和啓動工做。(可使用ps查看)

    Zygote進程會首先建立一個SystemServer進程,SystemServer進程負責啓動系統的關鍵服務,如包管理服務PackageManagerService和應用程序組件管理服務ActivityManagerService。

    當咱們須要啓動一個Android應用程序時,ActivityManagerService會經過Socket進程間通訊機制,通知Zygote進程爲這個應用程序建立一個新的進程。

相關文章
相關標籤/搜索