Android系统启动-Zygote进程启动过程

536 阅读13分钟

基于大佬的博客,在最新的android源码上记录自己的学习。 所参考博客,均贴出引用源,具体可参考原博主代码,可能更加详细。

因害怕忘记,故总结在此!

2024.7.13

源码基于Android 14

参考:袁辉辉大佬博客

1.Android系统启动-zygote篇

2.Android系统init.rc全解析

涉及到相关类的路径

platform/system/core/rootdir/init.rc
platform/system/core/rootdir/init.zygote32.rc
platform/frameworks/base/cmds/app_process/app_main.cpp
platform/frameworks/base/core/jni/AndroidRuntime.cpp
platform/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
platform/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
platform/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
platform/frameworks/base/core/java/com/android/internal/os/Zygote.java

1.什么是Zygote?

Zygote也称为孵化器。

普通应用程序进程和系统服务system_server进程都是用Zygote进程进行fork的。

Zygote进程在启动的时候会创建一个java虚拟机环境,因此通过fork创建的应用进程或者systemserver进程可以在内部获取到java虚拟机环境,就不会为每一个进程都创建虚拟机环境。

2.Zygote进程的创建

Zygote进程是由init进程通过解析init.zygoteXXX.rc创建的(XXX,这里根据系统是32位或者64位,或者兼容版本创建,init.zygote32.rc,init.zygote64.rc,init.zygote64_32.rc),相应的zygote进程所对应的可执行程序app_process(app_process64|app_process32),所对应的源文件是app_main.cpp,进程名是zygote。

参考:图解 Android 系列(二)深入理解 init 与 zygote 进程

init.zygote32.rc:zygote 进程对应的执行程序是 app_process(纯 32bit 模式)

init.zygote64.rc:zygote 进程对应的执行程序是 app_process64(纯 64bit 模式)。

init.zygote64_32.rc:启动两个 zygote 进程(名为 zygote 和 zygote_secondary),对应的执行程序分别是 app_process64(主模式)、app_process32(副模式)

以init.zygote32.rc为例

init进程通过解析init.rc文件启动一些服务,这些服务通常不是普通服务,而是daemon(守护进程),这里启动了zygote服务。

参考:Android系统init.rc全解析

rc文件基本命令类型。

  • import:表示引入其他的rc文件
  • on:表示一系列命令的组合
  • service:表示一个可执行程序

路径: core/rootdir/init.rc

//这里的${ro.zygote}会替换成具体的zygote32,zygote64或者zygote64_32
//这里的import表示导入rc文件,init.rc解析后会继续调用/system/etc/init/hw/init.${ro.zygote}.rc
import /system/etc/init/hw/init.${ro.zygote}.rc
​
//on表示一些列的命令组合,这里便是执行完init,进一步触发zygote-start
on late-init
    # Now we can start zygote.
    trigger zygote-start
​
​
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
//启动zygote
on zygote-start
    wait_for_prop odsign.verification.done 1
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier
    start statsd
    start netd
    start zygote    #启动zygote进程
    start zygote_secondary  #如果有两个zygote,启动另一个zygote进程
    
on userspace-reboot-resume
  trigger userspace-reboot-fs-remount
  trigger post-fs-data
  trigger zygote-start
  trigger early-boot
  trigger boot

路径:core/rootdir/init.zygote32.rc

//进程名zygote  运行的二进制文件在/system/bin/app_process
/*格式:name:服务名 pathname:当前服务对应的程序位置 argument 可选参数 option:当前服务设置的选项
*service <name> <pathname> [ <argument> ]*
*   <option>
*   <option>
*   ......
*/
//启动/system/bin/app_process目录下的zygote服务
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    # NOTE: If the wakelock name here is changed, then also
    # update it in SystemSuspend.cpp
    onrestart write /sys/power/wake_lock zygote_kwl
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart --only-if-running media.tuner
    onrestart restart netd
    onrestart restart wificond
    task_profiles ProcessCapacityHigh MaxPerformance
    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal
​

路径:base/cmds/app_process/Android.bp

不管是 app_process、app_process32 还是 app_process64,对应的源文件都是 app_main.cpp

cc_binary {
    name: "app_process",
​
    srcs: ["app_main.cpp"],
​
    multilib: {
        lib32: {
            suffix: "32",
        },
        lib64: {
            suffix: "64",
        },
    },
}

3.Zygote进程的启动过程

3.1 app_main.main

路径:base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
    if (!LOG_NDEBUG) {
      String8 argv_String;
      for (int i = 0; i < argc; ++i) {
        argv_String.append(""");
        argv_String.append(argv[i]);
        argv_String.append("" ");
      }
      ALOGV("app_process main with argv: %s", argv_String.c_str());
    }
    //传入的argv参数是 -Xzygote /system/bin --zygote --start-system-server
​
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // 忽略第一个参数
    argc--;
    argv++;
​
    ......
​
    // 参数解析,在识别到第一个没有识别的参数停止
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
​
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            //对于64位系统nice_name为zygote64,32位位zygote32
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName = (arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className = arg;
            break;
        } else {
            --i;
            break;
        }
    }
​
    Vector<String8> args;
    if (!className.empty()) {
        //非zygote模式
        ......
    } else {
        // 进入zygote模式
        maybeCreateDalvikCache();
​
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }
​
        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }
​
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);
​
        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }
​
    //使用nice_name 设置进程名
    if (!niceName.empty()) {
        runtime.setArgv0(niceName.c_str(), true /* setProcName */);
    }
​
    if (zygote) {
        //启动AppRuntime,AppRuntime继承于AndroidRuntime,实质上就是启动AndroidRuntime的start
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (!className.empty()) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        //没有制定类名或者zygote,参数错误
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

3.2 AndroidRuntime.start

路径:base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
​
    static const String8 startSystemServer("start-system-server");
    // Whether this is the primary zygote, meaning the zygote which will fork system server.
    bool primary_zygote = false;
​
    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
            primary_zygote = true;
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }
    ......
​
    /* startVm启动虚拟机 */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);
​
    /*
     * 注册JNI方法
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
​
    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
​
    //等价 strArray= new String[options.size() + 1];
    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    //等价 strArray[0] = "com.android.internal.os.ZygoteInit"
    env->SetObjectArrayElement(strArray, 0, classNameStr);
​
    //等价 strArray[1] = "start-system-server";
    // strArray[2] = "--abi-list=xxx";
    //其中xxx为系统响应的cpu架构类型,比如arm64-v8a.
    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).c_str());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }
​
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
     //将"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit"
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        //这里的startClass就是ZygoteInit
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            //调用ZygoteInit.main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
​
#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    //释放相应对象的内存空间
    free(slashClassName);
​
}

3.2.1 启动虚拟机 startVM

路径:base/core/jni/AndroidRuntime.cpp

创建虚拟机,个人理解虚拟机就是JAVA运行环境,有虚拟机之后,java代码才能在上面跑,这里暂时不做具体描述。

//返回值是0表示创建成功
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote)
{
    ......
}

3.2.2 注册JNI函数 startReg

路径:base/core/jni/AndroidRuntime.cpp

#ifdef NDEBUG
    #define REG_JNI(name)      { name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
    };
#else
    #define REG_JNI(name)      { name, #name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
        const char* mName;
    };
#endif
​
* Register android native functions with the VM.
 */
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ATRACE_NAME("RegisterAndroidNatives");
    /*
     * This hook causes all future threads created in this process to be
     * attached to the JavaVM.  (This needs to go away in favor of JNI
     * Attach calls.)
     */
     //设置线程创建方法为javaCreateThreadEtc
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
​
    ALOGV("--- registering native functions ---\n");
​
    /*
     * Every "register" function calls one or more things that return
     * a local reference (e.g. FindClass).  Because we haven't really
     * started the VM yet, they're all getting stored in the base frame
     * and never released.  Use Push/Pop to manage the storage.
     */
    env->PushLocalFrame(200);
​
    //注册进程JNI方法
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);
​
    //createJavaThread("fubar", quickTest, (void*) "hello");
​
    return 0;
}
​
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方法,REG_JNI是结构体RegJNIRec的别名?
static const RegJNIRec gRegJNI[] = {
        REG_JNI(register_com_android_internal_os_RuntimeInit),
        REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
        REG_JNI(register_android_os_SystemClock),
        REG_JNI(register_android_util_CharsetUtils),
        REG_JNI(register_android_util_EventLog),
        ......
}
​
路径:libutils/Threads.cpp
void androidSetCreateThreadFunc(android_create_thread_fn func)
{
    gCreateThreadFn = func;
}
​
​

这里在注册JNI时候调用了register_jni_procs,调用array[i].mProc(env),array[i]指向gRegJNI数组,调用array[i].mProc就等价于调用其参数名所指向的函数。

例如REG_JNI(register_com_android_internal_os_RuntimeInit).mProc也就是进入了register_com_android_internal_os_RuntimeInit方法。

接下来以此举例

int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
            {"nativeFinishInit", "()V",
             (void*)com_android_internal_os_RuntimeInit_nativeFinishInit},
            {"nativeSetExitWithoutCleanup", "(Z)V",
             (void*)com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup},
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
        methods, NELEM(methods));
}

由此就可以从Native侧调用到java侧的RuntimeInit,在3.2 AndroidRuntime.start()最后通过反射 env->CallStaticVoidMethod调用到ZygoteInit.main。

3.3 ZygoteInit.main

路径:core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;
​
        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();
​
        // Zygote运行在它自己的进程空间
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }
​
        Runnable caller;
        try {
​
            RuntimeInit.preForkInit();
​
            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    //表示要启动的进程是systemserver,在创建zygote进程时候传入start-system-server
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }
​
           
            // 在一些配置下,我们避免过早的加载资源和类
            // 在一些情况下,我们会预加载一些内容,在我们首次fork时候In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
                //预加载
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            }
​
            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            //垃圾回收
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
​
            bootTimingsTraceLog.traceEnd(); // ZygoteInit
​
            Zygote.initNativeState(isPrimaryZygote);
​
            ZygoteHooks.stopZygoteNoThreadCreation();
​
            //创建ZygoteServer,注册socket的本地服务端
            zygoteServer = new ZygoteServer(isPrimaryZygote);
​
            if (startSystemServer) {
            //启动system_server
                Runnable r = forkSystemServer(abiList, zygoteSocketName, 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;
                }
            }
​
            Log.i(TAG, "Accepting command socket connections");
​
            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            //zygote服务端进入循环模式,等待AMS发起请求建立连接fork进程
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }
​
        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

3.3.1 预加载类和资源 preload

    static void preload(TimingsTraceLog bootTimingsTraceLog) {
        //开始预加载
        beginPreload();
        //预加载位于/system/etc/preloaded-classes文件中的类
        preloadClasses();
​
        cacheNonBootClasspathClassLoaders();
        //预加载资源,包含drawable和color资源
        Resources.preloadResources();
        
        maybePreloadGraphicsDriver();
        //通过System.loadLibrary()方法,预加载"android","compiler_rt","jnigraphics"这3个共享库
        preloadSharedLibraries();
        //预加载 文本连接符资源
        preloadTextResources();
        
        //仅用于zygote进程,用于内存共享的进程
        WebViewFactory.prepareWebViewInZygote();
        endPreload();
        warmUpJcaProviders();
        Log.d(TAG, "end preload");
​
        sPreloadComplete = true;
    }

对于类加载,主要是通过反射机制Class.forName(line, true, null)来加载。

对于资源加载,主要是com.android.internal.R.array.preloaded_drawables、com.android.internal.R.array.preloaded_color_state_lists、com.android.internal.R.array.preloaded_freeform_multi_window_drawables这些drawable和color资源,以便此时又Zygote加载到内存中。

Zygote进程记载了preload方法中的所有资源,当需要fork新进程时候,采用copy on write技术fork出一模一样的资源给新进程(加快应用的启动速度)。

zygote fork进程 by Gityuan.png

3.3.2 创建Socket本地的服务端 new ZygoteServer

路径:core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;
​
        final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
        if (!isRuntimeRestarted) {
            if (isPrimaryZygote) {
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START,
            startTime);
        } else if (zygoteSocketName.equals(Zygote.SECONDARY_SOCKET_NAME)) {
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START,
            startTime);
        }
        }
​
​
        Zygote.initNativeState(isPrimaryZygote);
​
        zygoteServer = new ZygoteServer(isPrimaryZygote);
​
​
    }

路径:core/java/com/android/internal/os/ZygoteServer.java

    ZygoteServer(boolean isPrimaryZygote) {
        mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
​
        if (isPrimaryZygote) {
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
        } else {
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
        }
​
        mUsapPoolSupported = true;
        fetchUsapPoolPolicyProps();
    }

路径:core/java/com/android/internal/os/Zygote.java

    static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
​
        try {
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
        }
​
        try {
            FileDescriptor fd = new FileDescriptor();
            //设置文件描述符
            fd.setInt$(fileDesc);
            //创建Socket的本地服务端
            return new LocalServerSocket(fd);
        } catch (IOException ex) {
            throw new RuntimeException(
                "Error building socket from file descriptor: " + fileDesc, ex);
        }
    }

3.3.3 创建并启动systemserver

准备参数并fork出systemserver进程,从下面的信息可以看出来systemserver进程的uid=1000,pid=1000,进程名是system_server,从zygote进程fork出新进程后,就要关闭

private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ......
​
        //systemserver进程的参数准备
        String[] args = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs;
​
        int pid;
​
        try {
            //创建commandBuffer
            ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
            try {
                //用于解析参数,生成目标格式
                parsedArgs = ZygoteArguments.getInstance(commandBuffer);
            } catch (EOFException e) {
                throw new AssertionError("Unexpected argument error for forking system server", e);
            }
            //关闭commandBuffer
            commandBuffer.close();
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);
​
            ......
​
            //请求创建systemserver
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
​
        /* 进入子进程systemserver */
        if (pid == 0) {
            //对于两个zygote进程的情况,需要等待第二个zygote进程创建完成
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            //关闭原有的socket连接
            zygoteServer.closeServerSocket();
            //完成systemserver进程剩下的工作
            return handleSystemServerProcess(parsedArgs);
        }
​
        return null;
    }

3.3.4 进入等待状态,等待客户端发起请求 runSelectLoop

路径:core/java/com/android/internal/os/ZygoteServer.java

    /**
     * 运行zygote进程的选择循环。在发生新连接时接受它们,并从连接中读取
     * 命令,每次读取一个产生请求的值。*@param abiList 该zygote支持的 ABI 列表。
     */
    Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
        ArrayList<ZygoteConnection> peers = new ArrayList<>();
​
        //mZygoteSocket和fd是在上面new ZygoteServer时候创建并设置的,mZygoteSocket        //是socket中的服务端,也就是zygote进程
        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null);
​
        mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
​
        while (true) {
            
            StructPollfd[] pollFDs;
​
            // Allocate enough space for the poll structs, taking into account
            // the state of the USAP pool for this Zygote (could be a
            // regular Zygote, a WebView Zygote, or an AppZygote).
            if (mUsapPoolEnabled) {
                usapPipeFDs = Zygote.getUsapPipeFDs();
                pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
            } else {
                pollFDs = new StructPollfd[socketFDs.size()];
            }
            
            ......
​
​
            int pollReturnValue;
            try {
                //处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
                pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
​
            if (pollReturnValue == 0) {
                
                ......
​
            } else {
                boolean usapPoolFDRead = false;
​
                while (--pollIndex >= 0) {
                    if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                        continue;
                    }
​
                    if (pollIndex == 0) {
                        // Zygote server socket
                        //即fds[0],代表的是sServerSocket,则意味着有客户端连接                          
                        //请求;则创建ZygoteConnection对象,并添加到fds。
                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
                        peers.add(newPeer);
                        socketFDs.add(newPeer.getFileDescriptor());
                    } else if (pollIndex < usapPoolEventFDIndex) {
                        // Session socket accepted from the Zygote server socket
                        // Session socket接受来自Zygote server socket的连接
​
                        try {
                            //通过pollIndex获取到ZygoteConnection
                            ZygoteConnection connection = peers.get(pollIndex);
                            boolean multipleForksOK = !isUsapPoolEnabled()
                                    && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
                            //执行processCommand
                            final Runnable command =
                                    connection.processCommand(this, multipleForksOK);
​
                            // TODO (chriswailes): Is this extra check necessary?
                            if (mIsForkChild) {
                                // We're in the child. We should always have a command to run at
                                // this stage if processCommand hasn't called "exec".
                                if (command == null) {
                                    throw new IllegalStateException("command == null");
                                }
​
                                return command;
                            } else {
                                // We're in the server - we should never have any commands to run.
                                if (command != null) {
                                    throw new IllegalStateException("command != null");
                                }
​
                                // We don't know whether the remote side of the socket was closed or
                                // not until we attempt to read from it from processCommand. This
                                // shows up as a regular POLLIN event in our regular processing
                                // loop.
                                if (connection.isClosedByPeer()) {
                                    connection.closeSocket();
                                    peers.remove(pollIndex);
                                    //处理完则从fds中移除该文件描述符
                                    socketFDs.remove(pollIndex);
                                }
                            }
                        } catch (Exception e) {
                            ......
                        } finally {
                            // Reset the child flag, in the event that the child process is a child-
                            // zygote. The flag will not be consulted this loop pass after the
                            // Runnable is returned.
                            mIsForkChild = false;
                        }
​
                    } else {
                        // Either the USAP pool event FD or a USAP reporting pipe.
​
                        // If this is the event FD the payload will be the number of USAPs removed.
                        // If this is a reporting pipe FD the payload will be the PID of the USAP
                        // that was just specialized.  The `continue` statements below ensure that
                        // the messagePayload will always be valid if we complete the try block
                        // without an exception.
                        long messagePayload;
​
                        try {
                            byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
                            int readBytes =
                                    Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
​
                            if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
                                DataInputStream inputStream =
                                        new DataInputStream(new ByteArrayInputStream(buffer));
​
                                messagePayload = inputStream.readLong();
                            } else {
                                Log.e(TAG, "Incomplete read from USAP management FD of size "
                                        + readBytes);
                                continue;
                            }
                        } catch (Exception ex) {
                            if (pollIndex == usapPoolEventFDIndex) {
                                Log.e(TAG, "Failed to read from USAP pool event FD: "
                                        + ex.getMessage());
                            } else {
                                Log.e(TAG, "Failed to read from USAP reporting pipe: "
                                        + ex.getMessage());
                            }
​
                            continue;
                        }
​
                        if (pollIndex > usapPoolEventFDIndex) {
                            Zygote.removeUsapTableEntry((int) messagePayload);
                        }
​
                        usapPoolFDRead = true;
                    }
                }
​
                
            }
​
            
        }
    }

4.总结

Zygote启动过程调用流程图

zygote进程启动.png

1.调用app_main的main方法,解析init.zygote.rc中参数,创建AppRuntime,并调用AndroidRuntime.start方法

2.在AndroidRuntime.start方法中调用startVM创建虚拟机,再调用startReg注册JNI函数;

3.通过JNI反射的方式调用到ZygoteInit.main方法,实现从native侧到java侧

4.ZygoteInit.main方法中调用preload预加载通用类、drawable和color资源,共享库和WebView,提升app的启动速度;注册zygotesocket建立socket通道,用于响应客户端的请求。

5.zygote的大部分工作完成,通过foreSystemServer创建出systemserver进程

6.创建完systemserver进程之后,zygote的工作基本完成,调用ZygoteServer.runSelectLoop方法,随时待命,接收到客户端请求创建新进程请求时候就立即唤醒并执行相应的工作。