Android启动流程分析(十一) zygote的启动

#############################################

本文为极度寒冰原创,转载请注明出处

#############################################

前面的文章花了很大的篇幅去介绍了init进程如何去解析init.rc,如何去执行系统的一些服务。

那么,我们所说的zygote是怎么启动的呢?zygote又是具体负责了哪些工作呢?

本文我们来一探究竟。

zygote在inir.rc中有如下的描述:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
我们可以简单的分析下这两句话,

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

    class main

这个是说,zygote是属于main的class。

zygote是一个服务,服务的名字叫zygote. 启动的时候执行的命令是app_process, 传递的参数是-Xzygote /system/bin --zygote --start-system-server

那么,按照我们前面分析的理论,我们去看一下app_process是个什么东西
首先我们到framework的目录下,在base/cmds/app_process里面,我们看到了生成app_process的makefile

include $(CLEAR_VARS)

LOCAL_SRC_FILES:=         app_main.cpp

LOCAL_SHARED_LIBRARIES :=         libcutils         libutils         liblog         libbinder         libandroid_runtime

LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
include $(BUILD_EXECUTABLE)
我们可以看到app_process被执行生成了一个应用程序。

试想一下,zygote的这个服务应该是一直在运行的,但是我们如果adb shell去看ps的话,并找不到app_process的这个命令在一直运行。

这个是为什么呢?

首先我们从app_process的main函数里面截取出来一段

    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) { // 如果从init.rc里面传进来的参数是带--zygote的话,一定是会进这个判断
            zygote = true;  // 将zygote设置为true
            niceName = ZYGOTE_NICE_NAME;  // 将niceName设置为zygote_nice_name设置为zygote
        } else if (strcmp(arg, "--start-system-server") == 0) { // 如果是要启动start-system-server的话
            startSystemServer = true; // 会将startsystemserver设置为true
        } else if (strcmp(arg, "--application") == 0) {  // 
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

然后这几个参数可以怎么去使用呢?

接着看一下后面的代码,是如何使用的。

    if (!niceName.isEmpty()) {  //如果niceName不为空的话
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string()); // 调用这个函数将这个process的name设置为zygote
    }

    if (zygote) { // zygote一定为true
        runtime.start("com.android.internal.os.ZygoteInit", args); //我们进入到了这个判断
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
我们可以看到,runtime是调用了start的方法区进行了这个zygote的启动的工作,那么我们这个runtime是调用的哪边的start呢?

我们在当前的appruntime里面,是没有相关start函数的实现。

那我们去他的父类里面去看一下。

class AppRuntime : public AndroidRuntime
androidruntime是怎么样的呢?里面有没有start的方法呢?

AndroidRunTime的实现位于:frameworks/base/core/jni/AndroidRuntime.cpp

我们从里面找到了start的方法。

951void AndroidRuntime::start(const char* className, const Vector<String8>& options)
952{
953    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
954            className != NULL ? className : "(unknown)", getuid());
955
956    static const String8 startSystemServer("start-system-server");
957
958    /*
959     * 'startSystemServer == true' means runtime is obsolete and not run from
960     * init.rc anymore, so we print out the boot start event here.
961     */
962    for (size_t i = 0; i < options.size(); ++i) {
963        if (options[i] == startSystemServer) {
964           /* track our progress through the boot sequence */
965           const int LOG_BOOT_PROGRESS_START = 3000;
966           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
967        }
968    }
969
970    const char* rootDir = getenv("ANDROID_ROOT");
971    if (rootDir == NULL) {
972        rootDir = "/system";
973        if (!hasDir("/system")) {
974            LOG_FATAL("No root directory specified, and /android does not exist.");
975            return;
976        }
977        setenv("ANDROID_ROOT", rootDir, 1);
978    }
979
980    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
981    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
982
983    /* start the virtual machine */
984    JniInvocation jni_invocation;
985    jni_invocation.Init(NULL);
986    JNIEnv* env;
987    if (startVm(&mJavaVM, &env) != 0) {    // 创建虚拟机
988        return;
989    }
990    onVmCreated(env);
991
992    /*
993     * Register android functions.
994     */
995    if (startReg(env) < 0) { // 注册jni的方法
996        ALOGE("Unable to register all android natives\n");
997        return;
998    }
999
1000    /*
1001     * We want to call main() with a String array with arguments in it.
1002     * At present we have two arguments, the class name and an option string.
1003     * Create an array to hold them.
1004     */
1005    jclass stringClass;  // class对象
1006    jobjectArray strArray; // 对应objectArray对象
1007    jstring classNameStr; // 一个string
1008
1009    stringClass = env->FindClass("java/lang/String"); //首先找到了string的class
1010    assert(stringClass != NULL);
1011    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);  // New 了一个ObjectArray
1012    assert(strArray != NULL);
1013    classNameStr = env->NewStringUTF(className);  // 将className转换为UTF8的类型
1014    assert(classNameStr != NULL);
1015    env->SetObjectArrayElement(strArray, 0, classNameStr);  // 设置objectarray的第一个元素为classname
1016
1017    for (size_t i = 0; i < options.size(); ++i) {  // 将后续的参数依次经过转换push到strArray的数组中
1018        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
1019        assert(optionsStr != NULL);
1020        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
1021    }
1022
1023    /*
1024     * Start VM.  This thread becomes the main thread of the VM, and will
1025     * not return until the VM exits.
1026     */
1027    char* slashClassName = toSlashClassName(className); // 将className转换为/的形式
1028    jclass startClass = env->FindClass(slashClassName); // 寻找这个类
1029    if (startClass == NULL) { // 如果找不到的话,我们会返回NULL
1030        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
1031        /* keep going */
1032    } else {
1033        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
1034            "([Ljava/lang/String;)V");   // 获取我们寻找到的这个类的main函数
1035        if (startMeth == NULL) {
1036            ALOGE("JavaVM unable to find main() in '%s'\n", className);
1037            /* keep going */
1038        } else {
1039            env->CallStaticVoidMethod(startClass, startMeth, strArray); // 去执行这个类的main函数的方法。
1040
1041#if 0
1042            if (env->ExceptionCheck())
1043                threadExitUncaughtException(env);
1044#endif
1045        }
1046    }
1047    free(slashClassName);  // free
1048
1049    ALOGD("Shutting down VM\n");
1050    if (mJavaVM->DetachCurrentThread() != JNI_OK)
1051        ALOGW("Warning: unable to detach main thread\n");
1052    if (mJavaVM->DestroyJavaVM() != 0)
1053        ALOGW("Warning: VM did not shut down cleanly\n");
1054}
来根据刚才传递的参数来看一下zygoteInit的main函数

648    public static void main(String argv[]) {
649        try {
650            // Start profiling the zygote initialization.
651            SamplingProfilerIntegration.start();
652
653            boolean startSystemServer = false;
654            String socketName = "zygote";
655            String abiList = null;
656            for (int i = 1; i < argv.length; i++) {
657                if ("start-system-server".equals(argv[i])) {
658                    startSystemServer = true;  // startSystemServer为true
659                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
660                    abiList = argv[i].substring(ABI_LIST_ARG.length());
661                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
662                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
663                } else {
664                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
665                }
666            }
667
668            if (abiList == null) {
669                throw new RuntimeException("No ABI list supplied.");
670            }
671
672            registerZygoteSocket(socketName); // 注册了一个socket,用来与系统中的其他应用程序进行通信
673            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
674                SystemClock.uptimeMillis());
675            preload(); // 预加载一些资源
676            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
677                SystemClock.uptimeMillis());
678
679            // Finish profiling the zygote initialization.
680            SamplingProfilerIntegration.writeZygoteSnapshot();
681
682            // Do an initial gc to clean up after startup
683            gc();
684
685            // Disable tracing so that forked processes do not inherit stale tracing tags from
686            // Zygote.
687            Trace.setTracingEnabled(false);
688
689            if (startSystemServer) {  // 如果startSystemServer为true的话,我们会启动systemServer
690                startSystemServer(abiList, socketName);
691            }
692
693            Log.i(TAG, "Accepting command socket connections");
694            runSelectLoop(abiList);  // 进入select的循环,用来响应其他应用程序的请求
695
696            closeServerSocket();
697        } catch (MethodAndArgsCaller caller) {
698            caller.run();
699        } catch (RuntimeException ex) {
700            Log.e(TAG, "Zygote died with exception", ex);
701            closeServerSocket();
702            throw ex;
703        }
704    }
那么,最后我们对zygote进行一下总结

首先zygote创建了appruntime的对象,并调用他的start。此后的活动由AppRuntime来控制

然后调用startVM来创建了虚拟机,调用startReg来注册JNI的函数

通过JNI调用zygoteInit进入了java的世界

调用registerZygoteSocket来响应子孙后代的请求,同时调用preload函数进行资源的预加载

调用startSystemServer来进行系统启动的后续工作

完成了java世界的初创工作后,变进入了select循环,来处理后续的请求。







郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。