Zygote进程启动流程

408 阅读5分钟

一、启动入口

在 Android 8.0 版本后, 对 init.rc 文件进行了拆分,每个服务对应一个 rc 文件。

  • init.XXX.rc 文件:这里的 XXX 代指不同的服务,是多个非常重要的配置文件。该文件是由 Android 初始化语言 Android Init Language 编写的脚本。例如 Zygote 启动脚本在 init.zygoteXX.rc 中定义,XX 是处理器位数,例如 64 位处理器是 init.zygote64.rc 。

从 Android5.0 开始, Android 开始支持 64 位程序, Zygote 有了 32 和 64 位的区别, ro.zygote 的取值有以下四种:

  • init.zygote32.rc :表示支持纯 32 位程序。
  • init.zygote64.rc : 表示支持纯 64 位程序。
  • init.zygote32_64.rc :表示即支持 32 位程序也支持 64 位程序;脚本中有两个 Service ,会启动两个 Zygote 进程:
    • 一个名为 zygote,执行程序为 app_process32 ,作为主模式;
    • 另一个名为 zygotę_secondary ,执行程序为 app_process64 ,作为辅模式。
  • init.zygote64_32.rc:主模式与辅模式正好与 32_64 相反。

这里以zygote64_32.rc为例 源码如下: /system/core/rootdir/init.zygote64_32.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
// 660 权限 只有拥有者有读写权限;而属组用户和其他用户只有读权限。
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
// 创建子进程时,向 /dev/cpuset/foreground/tasks 写入pid
writepid /dev/cpuset/foreground/tasks

    
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
writepid /dev/cpuset/foreground/tasks

上面的脚本大概的意思就是:

  • 通过Service命令通知 init 进程创建名为 zygote 的进程,zygote进程对应的路径为system/bin/app_process64
  • 启动的入口即是class main所指的main函数,而app_process64对应的代码定义在app_main.cpp中。
  • 后面的是要传给 app_process64 的参数。

二、app_main.cpp

frameworks/base/cmds/app_process/app_main.cpp

app_main.cppmain 函数的重要流程:

int main(int argc, char* const argv[])
{
    /* ... */
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    /* ... */
    ++i;	// 跳过第一个参数(父目录)
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            // 如果main函数运行在Zygote进程中,则将zygote设置为true
            zygote = true;
            // 设置进程的名字 
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            // 如果main函数运行在SystemServer进程中,则将startSystemServer设置为true
            startSystemServer = true;
        } 
        /* ... */
    }
    /* ... */
    if (zygote) {
        // 如果运行在Zygote进程中,则调用AppRuntime的start函数
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        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.");
    }
}

重要流程概括:

  • 判断当前 main函数是运行在 Zygote 进程还是 SystemServer 进程。

    Zygote 进程通过 fock 自身来创建子进程,因此 Zygote 进程和它的子进程都可以进入 app_main.cppmain 函数, 所以 main 函数中必须区分当前运行在哪个进程。

  • 如果运行在 Zygote 进程中,则调用 AppRuntime 的 start 函数来启动 Java 虚拟机。

    AppRuntime又继承于AndroidRuntimeAppRuntime中并没有重写父类的start()方法,所以这里start()方法调用的是AndroidRuntimestart()方法。

三、AndroidRuntime.cpp

frameworks/base/core/jni/AndroidRuntime.cpp

AndroidRuntime.cppstart 函数的重要流程:

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    /* ... */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    // 创建Java虚拟机
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    // 对虚拟机进行初始化  
    onVmCreated(env);

    // 为Java虚拟机注册JNI方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /* ... */
    // 从 app_main的main函数传递过来的className为com.android.internal.os.ZygoteInit
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    // 启动虚拟机,该线程成为虚拟机的主线程,直到虚拟机退出后才返回。
    // 将className的“.”替换为“/”
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    // 查找ZygoteInit这个Java类
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
    } else {
        // 找到ZygoteInit的main方法
        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 {
            // 通过JNI调用ZygoteInit的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
            /* ... */
        }
    }
    /* ... */
}

重要流程概括:

  • 调用 startVm 函数来创建 Java 虚拟机。
  • 调用 startReg 函数为 Java 虚拟机注册 JNI 方法。
  • 将传递过来的参数 className 的值 com.android.internal.os.ZygoteInit 中的.替换为/,即 com/android/internal/os/ZygoteInit,并赋值给 slashClassName
  • 根据 slashClassName 去查找 Zygotelnit 类。
  • 如果找到了,则通过 JNI 调用 ZygoteInitmain 方法。

⭐️ 在此之前,一直在 native 层运行,没有任何代码进入 Java 框架层,也就是说是 Zygote 开启了 Java 框架层的运行。

四、ZygoteInit.java

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

ZygoteInit.javamain 方法和 startSystemServer 方法的重要流程

不同版本,代码略有差别:

以下是 Android 8.0 中的 ZygoteInit 类。

public static void main(String argv[]) {
    // 创建ZygoteServer对象
    ZygoteServer zygoteServer = new ZygoteServer();
    /* ... */
    try {
        /* ... */
        String socketName = "zygote";
        /* ... */
        // 创建一个Server端的Socket,并传入socketName
        zygoteServer.registerServerSocket(socketName);
        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();
        } else {
            Zygote.resetNicePriority();
        }
		/* ... */
        if (startSystemServer) {
            // 启动SystemServer进程,并捕获Zygote.MethodAndArgsCaller异常
            startSystemServer(abiList, socketName, zygoteServer);
        }
        Log.i(TAG, "Accepting command socket connections");
        // 等待AMS创建新应用程序进程的请求
        zygoteServer.runSelectLoop(abiList);
        zygoteServer.closeServerSocket();
    } catch (Zygote.MethodAndArgsCaller caller) {
        // SystemServer进程完成初始化,调用run方法
        caller.run();
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        zygoteServer.closeServerSocket();
        throw ex;
    }
}

private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
        throws Zygote.MethodAndArgsCaller, RuntimeException {
    /* ... */
    // 创建args数组,保存启动SystemServer的启动参数
    String args[] = {
        "--setuid=1000", 	// 用户id
        "--setgid=1000",	// 用户组id
        // 进程拥有的权限
        "--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",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

    try {
        // 将args数组封装成Arguments对象
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        // 创建一个子进程,即SystemServer进程
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    // 当前代码逻辑运行在子进程中
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
		// 关闭Zygote进程创建的Socket
        zygoteServer.closeServerSocket();
        // 处理SystemServer进程
        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

重要流程概括:

  • 通过 registerServerSocket 方法创建一个 Server 端名为 zygote 的 Socket 对象,并通过runSelectLoop 方法无限循环等待 ActivityManagerService 的请求,一旦有请求,则调用 ZygoteConnectionrunOnce 函数来创建一个新的应用程序进程。
  • 预加载公共类和公共资源,而这些资源可以通过 fork 的方式,共享给它的全部子进程。
  • 启动 SystemServer 进程。