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

来源:互联网 发布:算法第四版英文版pdf 编辑:程序博客网 时间:2024/06/06 04:51

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

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

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

前面的文章花了很大的篇幅去介绍了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.cppLOCAL_SHARED_LIBRARIES := \        libcutils \        libutils \        liblog \        libbinder \        libandroid_runtimeLOCAL_MODULE:= app_processLOCAL_MULTILIB := bothLOCAL_MODULE_STEM_32 := app_process32LOCAL_MODULE_STEM_64 := app_process64include $(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());955956    static const String8 startSystemServer("start-system-server");957958    /*959     * 'startSystemServer == true' means runtime is obsolete and not run from960     * 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    }969970    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    }979980    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");981    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);982983    /* 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);991992    /*993     * Register android functions.994     */995    if (startReg(env) < 0) { // 注册jni的方法996        ALOGE("Unable to register all android natives\n");997        return;998    }9991000    /*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; // 一个string10081009    stringClass = env->FindClass("java/lang/String"); //首先找到了string的class1010    assert(stringClass != NULL);1011    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);  // New 了一个ObjectArray1012    assert(strArray != NULL);1013    classNameStr = env->NewStringUTF(className);  // 将className转换为UTF8的类型1014    assert(classNameStr != NULL);1015    env->SetObjectArrayElement(strArray, 0, classNameStr);  // 设置objectarray的第一个元素为classname10161017    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    }10221023    /*1024     * Start VM.  This thread becomes the main thread of the VM, and will1025     * not return until the VM exits.1026     */1027    char* slashClassName = toSlashClassName(className); // 将className转换为/的形式1028    jclass startClass = env->FindClass(slashClassName); // 寻找这个类1029    if (startClass == NULL) { // 如果找不到的话,我们会返回NULL1030        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函数的方法。10401041#if 01042            if (env->ExceptionCheck())1043                threadExitUncaughtException(env);1044#endif1045        }1046    }1047    free(slashClassName);  // free10481049    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();652653            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为true659                } 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            }667668            if (abiList == null) {669                throw new RuntimeException("No ABI list supplied.");670            }671672            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());678679            // Finish profiling the zygote initialization.680            SamplingProfilerIntegration.writeZygoteSnapshot();681682            // Do an initial gc to clean up after startup683            gc();684685            // Disable tracing so that forked processes do not inherit stale tracing tags from686            // Zygote.687            Trace.setTracingEnabled(false);688689            if (startSystemServer) {  // 如果startSystemServer为true的话,我们会启动systemServer690                startSystemServer(abiList, socketName);691            }692693            Log.i(TAG, "Accepting command socket connections");694            runSelectLoop(abiList);  // 进入select的循环,用来响应其他应用程序的请求695696            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循环,来处理后续的请求。







0 0
原创粉丝点击