android進階之瞭解Zygote進程的啓動及「孵化

Zygote進程基礎介紹java

Zygote中文翻譯爲「受精卵」,正如其名,它主要用於孵化子進程。在Android系統中有如下兩種程序:
1. java應用程序,主要基於ART虛擬機,全部的應用程序apk都屬於這類
2. native程序,也就是利用C或C++語言開發的程序,如bootanimation。android

全部的Java應用程序進程及系統服務SystemServer進程都由Zygote進程經過Linux的fork()函數孵化出來的,這也就是爲何把它稱爲Zygote的緣由,由於他就像一個受精卵,孵化出無數子進程,而native程序則由Init程序建立啓動。Zygote進程最初的名字不是「zygote」而是「app_process」,這個名字是在Android.mk文件中定義的。數組

如圖所示爲Zygote孵化框架:app

Zygote是一個C/S模型,Zygote進程做爲服務端,其餘進程做爲客戶端向它發出「孵化」請求,而Zygote接收到這個請求後就「孵化」出一個新的進程。如圖所示,當點擊Launcher裏的應用程序圖標去啓動一個新的應用程序進程時,這個請求會到達框架層的核心服務ActivityManagerService中,當AMS收到這個請求後,它經過調用Process類發出一個「孵化」子進程的Socket請求,而Zygote監聽到這個請求後就馬上fork一個新的進程出來。
Zygote進程的啓動框架

Zygote進程對應的主文件爲app_main.cpp,當他被Init進程啓動起來以後,就會進入主文件app_main.cpp的main()函數。接下來它的main函數開始分析Zygote進程的啓動:socket

int main(int argc, char* const argv[])
{
    .......
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            //說明啓動的是Zygote進程
            niceName = ZYGOTE_NICE_NAME;
            //ZYGOTE_NICE_NAME字符串內容就是「Zygote」,此處已被換名字
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
            //在init.rc裏配置了前面的這些參數,而Zygote進程啓動的時候,
            //Init進程會傳過來這些參數,因此此處把變量startSystemServer
            //設置爲true表明啓動SystemServer
        } else if (strcmp(arg, "--application") == 0)
        .......
    }
    ......ide

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        //zygote爲true表明的是Zygote進程,也就是說如今正在啓動的是Zygote進程,
        //咱們知道Zygote進程用於孵化子進程,Zygote進程孵化子進程是經過本身的資源賦值一份,
        //來fork一個新的子進程,也就是說子進程也會進入這個文件的main函數,所以,
        //這裏的main函數被調用並不僅是Zygote啓動的時候被調用。這裏經過zygote這個變量來區分,
        //若是是Zygote進程自己,就會進入到if裏,不然就會進入到下面的else if裏,表明字進程啓動。
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        .......
    }
}函數

main()函數最後調用runtime的start()函數,runtime是一個AppRuntime對象,看看AppRuntime類:oop

class AppRuntime : public AndroidRuntime
{
    .......
}post

AppRuntime類繼承AndroidRuntime類,所以前面調用的runtime的start()函數就會進入AndroidRuntime的start()函數,下面看看該函數:

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ......
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //啓動VM
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    //註冊JNI函數
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ....
    //className由上一步傳遞過來,「com.android.internal.os.ZygoteInit」或者「com.android.internal.os.RuntimeInit」
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
    } else {
        //代表要調用的是類的main()函數
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
        } else {
            //調用ZygoteInit的main()函數或RuntimeInit的main()函數
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
    .......
}

AndroidRuntime的start()函數主要作了如下三件事情:
1. 調用startVM()函數啓動虛擬機
2. 調用startReg()函數註冊JNI方法
3. 調用com.android.internal.os.ZygoteInit類的main()函數(如果子進程,則調用com.android.internal.os.RuntimeInit的main()函數,從而基本結束初始化。而Zygote進程的main函數則還有如下的會講到的5項工做)

下面一一介紹三個函數的具體工做:
啓動虛擬機

經過調用startVM()函數啓動虛擬機:

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    ......
    //經過調用JNI_CreateJavaVM()建立虛擬機,若是對這個感興趣,能夠去研究下art虛擬機
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }
    ......
}

註冊JNI方法

在Android中,Java世界要調用native世界的函數就要用JNI機制,而且在Android系統中也大量使用JNI機制,Android系統經過以下的startReg()函數去註冊:

/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ......
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    .......
}

startReg()函數經過調用register_jni_procs()函數去進一步註冊,傳遞的值是gRegJNI數組,原生Android6.0版本該數組超過130個,具體以下:

static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_com_android_internal_os_ZygoteInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_EventLog),
    REG_JNI(register_android_util_Log),
    REG_JNI(register_android_util_MemoryIntArray),
    REG_JNI(register_android_util_PathParser),
    REG_JNI(register_android_app_admin_SecurityLog),
    REG_JNI(register_android_content_AssetManager),
    REG_JNI(register_android_content_StringBlock),
    REG_JNI(register_android_content_XmlBlock),
    REG_JNI(register_android_text_AndroidCharacter),
    REG_JNI(register_android_text_StaticLayout),
    REG_JNI(register_android_text_AndroidBidi),
    REG_JNI(register_android_view_InputDevice),
    REG_JNI(register_android_view_KeyCharacterMap),
    REG_JNI(register_android_os_Process),
    REG_JNI(register_android_os_SystemProperties),
    REG_JNI(register_android_os_Binder),
    REG_JNI(register_android_os_Parcel),
    ......
}

上面所列的JNI都經過register_jni_procs()函數來註冊:

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
            ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
            return -1;
        }
    }
    return 0;
}

經過循環對全部的JNI函數進行註冊。。。
調用ZygoteInit類的main()

ZygoteInit是一個Java類,咱們終於走到了Java世界,看看該main()方法:

    public static void main(String argv[]) {
        ......
        try {
            ......
            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
            ........
            zygoteServer.registerServerSocket(socketName);
            .......
            preload(bootTimingsTraceLog);
            .......
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            .....
        } finally {
            zygoteServer.closeServerSocket();
        }

        if (caller != null) {
            caller.run();
        }
    }

ZygoteInit類的main()方法主要作了如下5項工做:
1. 調用ZygoteServer類的registerServerSocket()方法建立一個Zygote的Socket接口,用來和AMS通訊
2. 調用preload()預加載類和資源
3. 調用forkSystemServer()函數來啓動SystemServer進程,r.run()啓動其main()方法
4. 調用ZygoteServer類的runSelectLoop()函數在前面建立的Socket接口上進入一個無限循環,等待覈心服務AMS請求建立新的應用程序進程。
5. 調用caller.run()方法,啓動子進程直接進入子進程的main()方法(非system_server進程,該進程由r.run()啓動main()方法)

下面一一講解着五項工做的內容:
registerServerSocket()

經過調用ZygoteServer類的registerServerSocket()方法來建立一個Java層的LocalServerSocket對象,目的是等待建立新的應用程序進程請求:

    void registerServerSocket(String socketName) {
        if (mServerSocket == null) {
            .......
            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                mServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                .......
            }
        }
    }

preload()預加載類與資源

    static void preload(BootTimingsTraceLog bootTimingsTraceLog) {
        .......
        //加載類,經過反射加載framework下的preload-classes文件中的類
        preloadClasses();
        ......
        //加載資源,加載framework-res-apk的資源
        preloadResources();
        //這兩個方法比較耗時,Android啓動時間慢,這是其中一個緣由,加載的類和資源太多了,致使時間過長。
        //提供一種思路去優化開機速度,既然這兩個方法時間過長,就單獨開一個線程去執行它,不要放在這個主線程裏,能夠試試
        ......
        //加載OpenGL()
        preloadOpenGL();
        .....
        //加載共享庫
        preloadSharedLibraries();
        .....
    }
 

既然加載這些類和資源這麼耗時間,爲何還要預加載:
應用程序都從Zygote孵化出來,應用程序都會繼承Zygote的全部內容,若是在Zygote啓動的時候加載這些類和資源,這些孵化的應用程序就繼承Zygote的類和資源,這樣啓動引用程序的時候就不須要加載類和資源了,啓動的速度就會快不少。開機的次數很少,可是啓動應用程序的次數很是多。
啓動SystemServer進程

後續咱們將分析啓動SystemServer進程,主要是比較啓動SystemServer進程與啓動普通應用程序進程的區別。
runSelectLoop()函數進入無限循環

    Runnable runSelectLoop(String abiList) {
        .......
        while (true) {
            if (i == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                ZygoteConnection connection = peers.get(i);
                final Runnable command = connection.processOneCommand(this);
                ......
        }
        .......
    }
 

在無限循環中,若是變量i==0,表示Zygote Socket服務尚未準備好;當i!=0時,表示正在等待客戶端來鏈接「Zygote」這個Socket。當有孵化子進程的請求時,就會調用ZygoteConnection類的processOneCommand()函數來建立子進程。
caller.run()函數

咱們將在啓動應用程序進程的時候分析caller.run()函數。
SystemServer進程
啓動syetem_server進程

從上面的學習可知,啓動系統服務system_server進程從ZygoteInit.java的main()方法調用forkSystemServer()方法開始,先看看該方法:

    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        .....
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
        .......
        try {
            ......
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.runtimeFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        .......
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

首先設置了system_server進程的uid。gid和groups,而後設置進程的名字爲」–nice-name=system_server」。接着調用forkSystemServer()函數來fork一個新的進程,他有兩個返回值,一個在當前進程中返回,另外一個在新建立的進程中返回,在當前進程中返回值是新建立的pid值,而新建立進程中的返回值是0。
若是pid==0,表示已經進入SystemServer子進程,因而先調用zygoteServer.closeServerSocket()關閉「Zygote」socket,因爲Zygote啓動過程當中建立一個「Zygote」Socket。而系統服務進程system_server也繼承了Socket,不用因此close它。接着調用了handleSystemServerProcess()方法:

    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
        .......
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        .......
    }

主要調用了ZygoteInit.zygoteInit()方法:

    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

zygoteInit()方法主要調用了ZygoteInit.nativeZygoteInit()和RuntimeInit.applicationInit()這兩個方法:
- nativeZygoteInit()主要執行Binder驅動程序初始化的相關工做,它調用以後system_server進程就能夠進行Binder進程通訊(),是個native方法。
- 調用applicationInit()方法主要是爲了進入SystemServer.java的main()方法

接下來看看RuntimeInit.applicationInit()方法:

    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ........
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

    private static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
        ..........
        return new MethodAndArgsCaller(m, argv);
    }

能夠看出applicationInit()方法調用findStaticMain()方法,而該方法經過反射獲取system-server的main()方法後返回一個MethodAndArgsCaller,這是一個Runnable:

    static class MethodAndArgsCaller implements Runnable {
        /** method to call */
        private final Method mMethod;
        /** argument array */
        private final String[] mArgs;
        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
            .......
            }
        }
    }

可見經過反射調用main()方法,但返回到哪呢?其實在上面的ZygoteInit類的main()方法中,在建立完system_server後直接調用,以下ZygoteInit類的main()方法代碼所示,Runnable類型的r調用r.run()方法:

    public static void main(String argv[]) {
        ......
        try {
            ........
            zygoteServer.registerServerSocket(socketName);
            .......
            preload(bootTimingsTraceLog);
            .......
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            .....
        } finally {
            zygoteServer.closeServerSocket();
        }

        if (caller != null) {
            caller.run();
        }
    }

SystemServer fork新進程

Init進程、Zygote進程和SystemServer進程都很是重要,由於任何一個死機否會出現重啓。從上面的講解中可知,SystemServer系統服務的啓動從ZygoteInit類的forkSystemServer()方法開始:

    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        .....
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
        .......
        try {
            ......
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.runtimeFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        .......
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }
        return null;
    }

主要調用了兩個方法,Zygote.forkSystemServer()和handleSystemServerProcess(),上面講解了handleSystemServerProcess(),如今主要分析Zygote.forkSystemServer():

    public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        // Resets nice priority for zygote process.
        resetNicePriority();
        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true);
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

主要調用了nativeForkSystemServer(),這是一個native方法,對應的實現以下:

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      runtime_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, NULL, NULL);
    //傳入了衆多參數來fork一個新的進程
  if (pid > 0) {
      ALOGI("System server process %d has been created", pid);
      gSystemServerPid = pid;
      int status;
      if (waitpid(pid, &status, WNOHANG) == pid) {
          ALOGE("System server process %d has died. Restarting Zygote!", pid);
          RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
      }
  }
  return pid;
}

主要調用了ForkAndSpecializeCommon()函數:

static pid_t ForkAndSpecializeCommon(......) {
    .....
    pid_t pid = fork();
    ......
    UnsetSigChldHandler();
    ......
}

主要調用了兩個函數,fork()函數來建立一個新的子進程,接下來看看UnsetSigChldHandler():

static void SetSigChldHandler() {
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SigChldHandler;

  int err = sigaction(SIGCHLD, &sa, NULL);
  if (err < 0) {
    ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
  }
}

SetSigChldHandler()設置了信號處理函數SigChldHandler,意思是子進程死亡以後,就會產生一個信號,Zygote進程受到該信號以後就會調用SigChldHandler()處理異常:

static void SigChldHandler(int /*signal_number*/) {
  pid_t pid;
  int status;
  int saved_errno = errno;

  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
    ........
    if (pid == gSystemServerPid) {
      kill(getpid(), SIGKILL);
    }
  }

變量gSystemServerPid表示SystemServer進程的pid,若SystemServer進程中止工做,那麼首先經過getpid()來獲取Zygote進程的pid,而後調用kill函數殺死它,即SystemServer中止工做以後,Zygote進程自殺,已達到Zygote與SystemServer生死與共的目的。

在Init進程的main()函數中有一個死循環,若是它的子進程Zygote中止工做,就會去重啓子進程,代碼以下:

int main(int argc,char** argv){
    ......
    while(true){
        if(!waiting_for_exec){
            execute_one_command();
            restart_processes();
            //重啓死掉的service,若是zygote死掉了,就重啓Zygote。
            .......
        }
    }
}

從這個過程可知,Init進程、Zygote進程、SystemServer進程緊密相連,任何一個都不能出問題。
SystemServer建立框架核心服務

當SystemServer啓動以後,就會進入main()方法,又在它的main()方法中調用run()方法。Android系統的核心服務AMS、WMS、PMS等就是在run()方法裏進行建立和初始化的,當它們建立以後,會經過ServiceManager的add_server()方法把它們加入到ServiceManager中統一管理。

public final class SystemServer {
    .......
    public static void main(String[] args) {
        new SystemServer().run();
    }
    ......
    private void run() {
        .....
        Looper.prepareMainLooper();
        //建立消息隊列
        System.loadLibrary("android_servers");
        //加載SystemServer須要的android_servers庫
        createSystemContext();
        //建立系統Context
        ......
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
        //這三個方法是建立系統核心服務的實現

        Looper.loop();
        //進入消息循環,不止是應用程序有消息隊列,SystemServer也有
    }
}

run()方法主要調用了三個重要的方法,在這三個方法中建立和初始化了重要的系統服務,如AMS、WMS、PMS等等。
APP應用程序進程

前面分析了Zygote如何啓動SystemServer子進程,接下來再分析Zygote如何啓動其餘子進程,也就是建立應用程序進程的過程,這個過程和建立SystemServer進程基本同樣。當點擊Launcher主界面的一個應用程序圖標時,若是這個應用程序還不曾啓動,就會啓動它。而判斷應用程序有沒有啓動和去啓動應用程序都由核心服務AMS來作,它的startProcessLocked()方法會真正地啓動應用程序子進程。

下面爲AMS的startProcessLocked()方法:

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        ......
        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
        ......
        ProcessStartResult startResult;
        startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, invokeWith, entryPointArgs);
            }
        .......
    }

AMS的startProcessLocked()方法調用Process類的start()方法爲應用程序建立新的進程,這裏的參數entryPoint爲「android.app.ActivityThread」,它是傳進去的第一個參數,也就是程序初始化進程時要加載的主文件Java類。當應用進程啓動以後,會把這個類加載到進程,調用它的main()方法做爲應用程序進程的入口。
Process類的start()直接調用了ZygoteProcess類的start()方法,該start()方法有直接調用了ZygoteProcess類的startViaZygote()方法,下面看看該方法實現:

    private Process.ProcessStartResult startViaZygote(final String processClass,final String niceName,final int uid, final int gid,final int[] gids,int runtimeFlags, int mountExternal,int targetSdkVersion,String seInfo,String abi,String instructionSet,String appDataDir,String invokeWith,String[] extraArgs)throws ZygoteStartFailedEx {
        ArrayList<String> argsForZygote = new ArrayList<String>();
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        ......
        synchronized(mLock) {
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }
 

首先給它設置值,包括uid、gid等。這些值是應用程序在安裝時系統分配好的。接着調用openZygoteSocketIfNeeded()方法來連接「zygote」Socket,連接Socket成功以後,就會調用zygoteSendArgsAndGetResult()方法來進一步處理。

先來看看openZygoteSocketIfNeeded()方法:

    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        .......
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
                primaryZygoteState = ZygoteState.connect(mSocket);
            }
        .......
    }

方法中的mSocket的值是「zygote」,經過connect()方法去連接「zygote」Socket。

接着看看zygoteSendArgsAndGetResult()方法:

    private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            ........
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;

            writer.write(Integer.toString(args.size()));
            writer.newLine();

            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                writer.write(arg);
                writer.newLine();
            }

            writer.flush();
            .......
    }
 

經過Socket寫入流writer把前面傳過來的那些參數寫進去,Socket即ZygoteServer類的runSelectLoop()方法監聽。寫入這些數據以後,ZygoteServer類的runSelectLoop()方法就能被監聽到。
看一下runSelectLoop()方法的關鍵實現代碼:

    Runnable runSelectLoop(String abiList) {
        .......
        if (i == 0) {
            ZygoteConnection newPeer = acceptCommandPeer(abiList);
            peers.add(newPeer);
            fds.add(newPeer.getFileDesciptor());
        } else {
            ZygoteConnection connection = peers.get(i);
            final Runnable command = connection.processOneCommand(this);
        ......
    }

進入ZygoteConnection類的processOneCommand()方法後:

    Runnable processOneCommand(ZygoteServer zygoteServer) {
        ........
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
                parsedArgs.appDataDir);

        try {
            if (pid == 0) {
                // in child
                zygoteServer.setForkChild();

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;

                return handleChildProc(parsedArgs, descriptors, childPipeFd);
        ........
    }

以前啓動SystemServer進程的代碼有點類似。此處是經過Zygote.forkAndSpecialize()來fork新的應用進程,而啓動systemserver進程是經過Zygote.forkSystemServer()來fork SystemServer進程。這裏經過handleChildProc()方法處理,而以前是嗲偶用handleSystemServerProcess()來處理。經過fork新的應用程序進程以後,返回pid等於0就表示進入子進程,因而調用handleChildProc()方法進一步處理:

    private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd) {
        ........
        return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,null /* classLoader */);
        .......
    }

到此處,後面便和上面同樣的了,惟一不一樣的是,SystemServer進程啓動以後進入的是主類SystemServer.java的main()函數,而這裏應用程序啓動起來後進入的是主類是ActivityThread.java的main()函數。

至此,Zygote進程以及Zygote進程啓動SystemServer進程和啓動應用程序進程就分析完畢了,Zygote進程爲了啓動SystemServer和啓動應用程序進程主要作了兩件事,一是初始化Binder驅動用來進行進程間通訊,二是經過反射進入main()方法。  

相關文章
相關標籤/搜索