跳转至

Zygote 启动流程

相关链接

什么是 Zygote 进程?

你应该去理论篇了解相关信息,简单来说,Zygote 是 Android 系统中一个特殊的进程,负责孵化(fork)新的应用进程。它预加载了大量的资源和类库,使得新进程能够快速启动。

1. init 进程启动 app_process

按照我们之前的介绍,Zygote 是由 init 进程启动的。我们可以在 init.rc 中找到对应启动:

/system/core/rootdir/init.rc
#line 526:528 
    # Now we can start zygote.
    trigger zygote-start

#line 1087:1095
# to start-zygote in device's init.rc to unblock zygote start.
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 zygote
    start zygote_secondary
系统会启动 zygote 和 zygote_secondary 服务。这两个服务声明于以下配置文件中:

/system/core/rootdir/init.zygote32.rc
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
/system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    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
/system/core/rootdir/init.zygote64_32.rc
import /system/etc/init/hw/init.zygote64.rc

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote_secondary stream 660 root system
    socket usap_pool_secondary stream 660 root system
    onrestart restart zygote
    task_profiles ProcessCapacityHigh MaxPerformance

可以看出,zygote 服务会启动 /system/bin/app_process(64) 进程,附带的参数是--zygote --start-system-server

2. app_process 启动 ZygoteInit

源码网站上并没有这个文件,我从 Android 9 的实体机中提取了这个文件,是一个 ELF 文件,IDA 启动。

/system/bin/app_process64 main()
1
2
3
4
5
6
7
  if ( (v55 & 0x100000000LL) != 0 )
  {
    p_com.android.internal.os.RuntimeInit = "com.android.internal.os.ZygoteInit";
    v42 = 1;
  }
  // ...
  android::AndroidRuntime::start(v61, p_com.android.internal.os.RuntimeInit, v58, v42);
在经过一系列参数比对后,启动了java层com.android.internal.os.ZygoteInit

app_process 对应的源码是 app_main.cpp

/frameworks/base/cmds/app_process/app_main.cpp
//line 263:282
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            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;
        }
    }
//line 309:311
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }
//line 335:343
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (!className.empty()) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }

可以看出,在--zygote --start-system-server参数下,最终会启动Java层的 com.android.internal.os.ZygoteInit 类,并将start-system-server放在arg中传入。

3. ZygoteInit 启动流程

ZygoteInit.java 在 /frameworks/base/core/java/com/android/internal/os/

ZygoteInit 的主要流程是预加载资源,如果参数里有 --start-system-server 则孵化 SystemServer,最后进入循环等待 AMS 的创建请求。

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// 检查参数 line 848:860
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    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]);
                }
            }
// 预加载资源供后续孵化用 line 879:889
            // In some configurations, we avoid preloading resources and classes eagerly.
            // 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
            }
// 循环等待创建请求 line 917:919
            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);

main 启动中会判断了传入参数有没有 --start-system-server,如果有则会孵化 SystemServer 进程。

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// line 817
    public static void main(String[] argv) {
// 检查 argv 里是否存在 `--start-system-server` 设置 startSystemServer 标志 line 848:850
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
// 孵化 SystemServer line 902:913
            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                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;
                }
            }

4. 结语

至此,我们已经了解了 Zygote 进程的启动流程,从 init 启动 app_process,再到 app_process 启动 ZygoteInit,最后 ZygoteInit 进入循环等待创建请求的阶段。下一步就将探索 Zygote 如何孵化 SystemServer 和处理来自 AMS 的请求并孵化新的应用进程。