Android系统启动之zyogte进程

作者: Lee_5566 | 来源:发表于2019-03-26 20:11 被阅读11次
    image.png

    目录

    第一篇:Android系统启动之bootloader
    第二篇:Android系统启动之Init流程(上)
    第三篇:Android系统启动之Init流程(下)
    第四篇:Android系统启动之init.rc文件解析过程
    第五篇:Android系统启动之zyogte进程

    zyogte进程

    ygote进程在android系统中有着及其中要的位置.
    可以说android系统中的进程都是有zygote孵化出来的, 所有应用进程都是zygote的子进程.
    参考图片:


    image.png

    init进启动zygote服务,zygote进程再启动其他进程.
    首先,分析一下zygote服务的init.rc是如何执行的.

    从init.rc文件启动zyogte进程

    首先我们先来看下init.rc文件:(路径为:system/core/rootdir
    其中有这么一句话:

    import /init.${ro.zygote}.rc
    

    将同目录下的init.zyogtexx.rc文件加载.

    为什么是四个文件

    文件 含义
    init.zygote32.rc zygote 进程对应的执行程序是 app_process (纯 32bit 模式)
    init.zygote64.rc zygote 进程对应的执行程序是 app_process64 (纯 64bit 模式)
    init.zygote32_64.rc 启动两个 zygote 进程 (名为 zygote 和 zygote_secondary),对应的执行程序分别是 app_process32 (主模式)、app_process64
    init.zygote64_32.rc 启动两个 zygote 进程 (名为 zygote 和 zygote_secondary),对应的执行程序分别是 app_process64 (主模式)、app_process32

    init.zygote64.rc为例:

    service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
        class main
        priority -20
        user root
        group root readproc
        socket zygote 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
        writepid /dev/cpuset/foreground/tasks
    

    找到了zygote的启动设定,再来看下它的启动事件:
    文件system/core/rootdir/init.rc

    # It is recommended to put unnecessary data/ initialization from post-fs-data
    # to start-zygote in device's init.rc to unblock zygote start.
    on zygote-start && property:ro.crypto.state=unencrypted
        # A/B update verifier that marks a successful boot.
        exec_start update_verifier_nonencrypted
        start netd
        start zygote
        start zygote_secondary
    
    on zygote-start && property:ro.crypto.state=unsupported
        # A/B update verifier that marks a successful boot.
        exec_start update_verifier_nonencrypted
        start netd
        start zygote
        start zygote_secondary
    
    on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
        # A/B update verifier that marks a successful boot.
        exec_start update_verifier_nonencrypted
        start netd
        start zygote
        start zygote_secondary
    

    继续反向推理,发现zygote-start 的触发是在on late-init中:


    image.png

    那么late-init 在哪儿触发的呢?
    init.cpp中main函数中可以看到:

    image.png

    这样就启动了zyogte进程.O(∩_∩)O哈哈~

    app_process

    从上文的rc文件可以知道,zyogte进程的原型是/system/bin/app_process64
    代码路径为:rameworks/base/cmds/app_process

    先来看下mk文件:

    LOCAL_PATH:= $(call my-dir)
    
    app_process_common_shared_libs := \
        libandroid_runtime \
        libbinder \
        libcutils \
        libdl \
        libhwbinder \
        liblog \
        libnativeloader \
        libutils \
    
    # This is a list of libraries that need to be included in order to avoid
    # bad apps. This prevents a library from having a mismatch when resolving
    # new/delete from an app shared library.
    # See b/21032018 for more details.
    app_process_common_shared_libs += \
        libwilhelm \
    
    app_process_common_static_libs := \
        libsigchain \
    
    app_process_src_files := \
        app_main.cpp \
    
    app_process_cflags := \
        -Wall -Werror -Wunused -Wunreachable-code
    
    app_process_ldflags_32 := \
        -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic
    app_process_ldflags_64 := \
        -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic
    
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES:= $(app_process_src_files)
    
    LOCAL_LDFLAGS_32 := $(app_process_ldflags_32)
    LOCAL_LDFLAGS_64 := $(app_process_ldflags_64)
    
    LOCAL_SHARED_LIBRARIES := $(app_process_common_shared_libs)
    
    LOCAL_WHOLE_STATIC_LIBRARIES := $(app_process_common_static_libs)
    
    LOCAL_MODULE:= app_process
    LOCAL_MULTILIB := both
    LOCAL_MODULE_STEM_32 := app_process32
    LOCAL_MODULE_STEM_64 := app_process64
    
    LOCAL_CFLAGS += $(app_process_cflags)
    
    # In SANITIZE_LITE mode, we create the sanitized binary in a separate location (but reuse
    # the same module). Using the same module also works around an issue with make: binaries
    # that depend on sanitized libraries will be relinked, even if they set LOCAL_SANITIZE := never.
    #
    # Also pull in the asanwrapper helper.
    ifeq ($(SANITIZE_LITE),true)
    LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan
    LOCAL_REQUIRED_MODULES := asanwrapper
    endif
    
    include $(BUILD_EXECUTABLE)
    
    # Create a symlink from app_process to app_process32 or 64
    # depending on the target configuration.
    ifneq ($(SANITIZE_LITE),true)
    include  $(BUILD_SYSTEM)/executable_prefer_symlink.mk
    endif
    

    从Android.mk文件可以看出,app_process程序的来源就是文件app_main.cpp.

    代码文件app_main.cpp就是zyogte进程的源码.

    zyogte进程功能解析

    zyogte进程大致有两个功能:

    1. zygote模式,也就是初始化zygote进程.
    2. application模式,也就是启动普通应用程序.

    下面来分析一下app_main源文件的main函数:

    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.string());
        }
    
        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
        // Process command line arguments
        // ignore argv[0]
        argc--;
        argv++;
    
        // Everything up to '--' or first non '-' arg goes to the vm.
        //
        // The first argument after the VM args is the "parent dir", which
        // is currently unused.
        //
        // After the parent dir, we expect one or more the following internal
        // arguments :
        //
        // --zygote : Start in zygote mode
        // --start-system-server : Start the system server.
        // --application : Start in application (stand alone, non zygote) mode.
        // --nice-name : The nice name for this process.
        //
        // For non zygote starts, these arguments will be followed by
        // the main class name. All remaining arguments are passed to
        // the main method of this class.
        //
        // For zygote starts, all remaining arguments are passed to the zygote.
        // main function.
        //
        // Note that we must copy argument string values since we will rewrite the
        // entire argument block when we apply the nice name to argv0.
        //
        // As an exception to the above rule, anything in "spaced commands"
        // goes to the vm even though it has a space in it.
        const char* spaced_commands[] = { "-cp", "-classpath" };
        // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).
        bool known_command = false;
    
        int i;
        for (i = 0; i < argc; i++) {
            if (known_command == true) {
              runtime.addOption(strdup(argv[i]));
              ALOGV("app_process main add known option '%s'", argv[i]);
              known_command = false;
              continue;
            }
    
            for (int j = 0;
                 j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
                 ++j) {
              if (strcmp(argv[i], spaced_commands[j]) == 0) {
                known_command = true;
                ALOGV("app_process main found known command '%s'", argv[i]);
              }
            }
    
            if (argv[i][0] != '-') {
                break;
            }
            if (argv[i][1] == '-' && argv[i][2] == 0) {
                ++i; // Skip --.
                break;
            }
    
            runtime.addOption(strdup(argv[i]));
            ALOGV("app_process main add option '%s'", argv[i]);
        }
    //*******************************************************************
    //                       根据参数选择模式
    // 1.--zygote                 zygote模式
    // 2.--start-system-server    启动一个系统服务(app模式)
    // 3.--application            启动application(app模式)
    // 4.--nice-name=             修改名字(app模式)
    //*******************************************************************
        // Parse runtime arguments.  Stop at first unrecognized option.
        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;
                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.setTo(arg + 12);
            } else if (strncmp(arg, "--", 2) != 0) {
                className.setTo(arg);
                break;
            } else {
                --i;
                break;
            }
        }
    
        Vector<String8> args;
    //*******************************************************************
    //                       application模式
    //*******************************************************************
        if (!className.isEmpty()) {
            // We're not in zygote mode, the only argument we need to pass
            // to RuntimeInit is the application argument.
            //
            // The Remainder of args get passed to startup class main(). Make
            // copies of them before we overwrite them with the process name.
            args.add(application ? String8("application") : String8("tool"));
            runtime.setClassNameAndArgs(className, argc - i, argv + i);
    
            if (!LOG_NDEBUG) {
              String8 restOfArgs;
              char* const* argv_new = argv + i;
              int argc_new = argc - i;
              for (int k = 0; k < argc_new; ++k) {
                restOfArgs.append("\"");
                restOfArgs.append(argv_new[k]);
                restOfArgs.append("\" ");
              }
              ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
            }
        } else {
    //*******************************************************************
    //                       zygote模式
    //*******************************************************************
            // We're in zygote mode.
            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]));
            }
        }
    
        if (!niceName.isEmpty()) {
            runtime.setArgv0(niceName.string(), true /* setProcName */);
        }
    
        if (zygote) {
            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.");
        }
    }
    

    加了一点注释O(∩_∩)O哈哈~
    代码最后的runtime.start函数,就是要启动虚拟机了.

      if (zygote) {
    //zygote模式
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        } else if (className) {
    //app模式
            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.");
        }
    

    runtime是AndroidRuntime类的对象.
    这个类的实现在文件:frameworks/base/core/jni/AndroidRuntime.cpp中:

    AndroidRuntime类

    start函数中主要分为两部

    1. 初始化jni
    2. 启动虚拟机
      代码:
    oid AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
    
        ...
    
        /* start the virtual machine */
    //**********************************************
    //                   初始化JNI
    //***********************************************
        JniInvocation jni_invocation;
        jni_invocation.Init(NULL);
        JNIEnv* env;
    //**********************************************
    //                  启动虚拟机
    //***********************************************
        if (startVm(&mJavaVM, &env, zygote) != 0) {
            return;
        }
        onVmCreated(env);
        ... 
    }
    

    启动虚拟机

    /*
     * Start the Dalvik Virtual Machine.
     *
     * Various arguments, most determined by system properties, are passed in.
     * The "mOptions" vector is updated.
     *
     * CAUTION: when adding options in here, be careful not to put the
     * char buffer inside a nested scope.  Adding the buffer to the
     * options using mOptions.add() does not copy the buffer, so if the
     * buffer goes out of scope the option may be overwritten.  It's best
     * to put the buffer at the top of the function so that it is more
     * unlikely that someone will surround it in a scope at a later time
     * and thus introduce a bug.
     *
     * Returns 0 on success.
     */
    int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
    {
        JavaVMInitArgs initArgs;
        char propBuf[PROPERTY_VALUE_MAX];
        char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX];
        char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
        char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
        char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
        char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
        char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
        char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
        char usejitOptsBuf[sizeof("-Xusejit:")-1 + PROPERTY_VALUE_MAX];
        char jitmaxsizeOptsBuf[sizeof("-Xjitmaxsize:")-1 + PROPERTY_VALUE_MAX];
        char jitinitialsizeOptsBuf[sizeof("-Xjitinitialsize:")-1 + PROPERTY_VALUE_MAX];
        char jitthresholdOptsBuf[sizeof("-Xjitthreshold:")-1 + PROPERTY_VALUE_MAX];
        char useJitProfilesOptsBuf[sizeof("-Xjitsaveprofilinginfo:")-1 + PROPERTY_VALUE_MAX];
        char jitprithreadweightOptBuf[sizeof("-Xjitprithreadweight:")-1 + PROPERTY_VALUE_MAX];
        char jittransitionweightOptBuf[sizeof("-Xjittransitionweight:")-1 + PROPERTY_VALUE_MAX];
        char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
        char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
        char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
        char cachePruneBuf[sizeof("-Xzygote-max-boot-retry=")-1 + PROPERTY_VALUE_MAX];
        char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
        char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
        char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
        char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
        char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
        char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
        char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
        char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
        char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
        char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX];
        char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
        char dex2oat_isa_features[sizeof("--instruction-set-features=") -1 + PROPERTY_VALUE_MAX];
        char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
        char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
        char extraOptsBuf[PROPERTY_VALUE_MAX];
        char voldDecryptBuf[PROPERTY_VALUE_MAX];
        enum {
          kEMDefault,
          kEMIntPortable,
          kEMIntFast,
          kEMJitCompiler,
        } executionMode = kEMDefault;
        char localeOption[sizeof("-Duser.locale=") + PROPERTY_VALUE_MAX];
        char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
        char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];
        char cpuAbiListBuf[sizeof("--cpu-abilist=") + PROPERTY_VALUE_MAX];
        char methodTraceFileBuf[sizeof("-Xmethod-trace-file:") + PROPERTY_VALUE_MAX];
        char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
        char fingerprintBuf[sizeof("-Xfingerprint:") + PROPERTY_VALUE_MAX];
    
        bool checkJni = false;
        property_get("dalvik.vm.checkjni", propBuf, "");
        if (strcmp(propBuf, "true") == 0) {
            checkJni = true;
        } else if (strcmp(propBuf, "false") != 0) {
            /* property is neither true nor false; fall back on kernel parameter */
            property_get("ro.kernel.android.checkjni", propBuf, "");
            if (propBuf[0] == '1') {
                checkJni = true;
            }
        }
        ALOGV("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
        if (checkJni) {
            /* extended JNI checking */
            addOption("-Xcheck:jni");
    
            /* with -Xcheck:jni, this provides a JNI function call trace */
            //addOption("-verbose:jni");
        }
    
        property_get("dalvik.vm.execution-mode", propBuf, "");
        if (strcmp(propBuf, "int:portable") == 0) {
            executionMode = kEMIntPortable;
        } else if (strcmp(propBuf, "int:fast") == 0) {
            executionMode = kEMIntFast;
        } else if (strcmp(propBuf, "int:jit") == 0) {
            executionMode = kEMJitCompiler;
        }
    
        parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");
    
        strcpy(jniOptsBuf, "-Xjniopts:");
        if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) {
            ALOGI("JNI options: '%s'\n", jniOptsBuf);
        }
    
        /* route exit() to our handler */
        addOption("exit", (void*) runtime_exit);
    
        /* route fprintf() to our handler */
        addOption("vfprintf", (void*) runtime_vfprintf);
    
        /* register the framework-specific "is sensitive thread" hook */
        addOption("sensitiveThread", (void*) runtime_isSensitiveThread);
    
        /* enable verbose; standard options are { jni, gc, class } */
        //addOption("-verbose:jni");
        addOption("-verbose:gc");
        //addOption("-verbose:class");
    
        /*
         * The default starting and maximum size of the heap.  Larger
         * values should be specified in a product property override.
         */
        parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
        parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
    
        parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
        parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
        parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
        parseRuntimeOption("dalvik.vm.heaptargetutilization",
                           heaptargetutilizationOptsBuf,
                           "-XX:HeapTargetUtilization=");
    
        /*
         * JIT related options.
         */
        parseRuntimeOption("dalvik.vm.usejit", usejitOptsBuf, "-Xusejit:");
        parseRuntimeOption("dalvik.vm.jitmaxsize", jitmaxsizeOptsBuf, "-Xjitmaxsize:");
        parseRuntimeOption("dalvik.vm.jitinitialsize", jitinitialsizeOptsBuf, "-Xjitinitialsize:");
        parseRuntimeOption("dalvik.vm.jitthreshold", jitthresholdOptsBuf, "-Xjitthreshold:");
        property_get("dalvik.vm.usejitprofiles", useJitProfilesOptsBuf, "");
        if (strcmp(useJitProfilesOptsBuf, "true") == 0) {
            addOption("-Xjitsaveprofilinginfo");
        }
    
        parseRuntimeOption("dalvik.vm.jitprithreadweight",
                           jitprithreadweightOptBuf,
                           "-Xjitprithreadweight:");
    
        parseRuntimeOption("dalvik.vm.jittransitionweight",
                           jittransitionweightOptBuf,
                           "-Xjittransitionweight:");
    
        property_get("ro.config.low_ram", propBuf, "");
        if (strcmp(propBuf, "true") == 0) {
          addOption("-XX:LowMemoryMode");
        }
    
        parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");
        parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");
    
        /*
         * Enable debugging only for apps forked from zygote.
         * Set suspend=y to pause during VM init and use android ADB transport.
         */
        if (zygote) {
          addOption("-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y");
        }
    
        parseRuntimeOption("dalvik.vm.lockprof.threshold",
                           lockProfThresholdBuf,
                           "-Xlockprofthreshold:");
    
        if (executionMode == kEMIntPortable) {
            addOption("-Xint:portable");
        } else if (executionMode == kEMIntFast) {
            addOption("-Xint:fast");
        } else if (executionMode == kEMJitCompiler) {
            addOption("-Xint:jit");
        }
    
        // If we are booting without the real /data, don't spend time compiling.
        property_get("vold.decrypt", voldDecryptBuf, "");
        bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) ||
                                 (strcmp(voldDecryptBuf, "1") == 0));
    
        // Extra options for boot.art/boot.oat image generation.
        parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,
                                   "-Xms", "-Ximage-compiler-option");
        parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,
                                   "-Xmx", "-Ximage-compiler-option");
        if (skip_compilation) {
            addOption("-Ximage-compiler-option");
            addOption("--compiler-filter=assume-verified");
        } else {
            parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,
                                "--compiler-filter=", "-Ximage-compiler-option");
        }
    
        // Make sure there is a preloaded-classes file.
        if (!hasFile("/system/etc/preloaded-classes")) {
            ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
                  strerror(errno));
            return -1;
        }
        addOption("-Ximage-compiler-option");
        addOption("--image-classes=/system/etc/preloaded-classes");
    
        // If there is a compiled-classes file, push it.
        if (hasFile("/system/etc/compiled-classes")) {
            addOption("-Ximage-compiler-option");
            addOption("--compiled-classes=/system/etc/compiled-classes");
        }
    
        property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
        parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");
    
        // Extra options for DexClassLoader.
        parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf,
                                   "-Xms", "-Xcompiler-option");
        parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf,
                                   "-Xmx", "-Xcompiler-option");
        if (skip_compilation) {
            addOption("-Xcompiler-option");
            addOption("--compiler-filter=assume-verified");
    
            // We skip compilation when a minimal runtime is brought up for decryption. In that case
            // /data is temporarily backed by a tmpfs, which is usually small.
            // If the system image contains prebuilts, they will be relocated into the tmpfs. In this
            // specific situation it is acceptable to *not* relocate and run out of the prebuilts
            // directly instead.
            addOption("--runtime-arg");
            addOption("-Xnorelocate");
        } else {
            parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,
                                "--compiler-filter=", "-Xcompiler-option");
        }
        parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option");
        parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j",
                            "-Ximage-compiler-option");
    
        // The runtime will compile a boot image, when necessary, not using installd. Thus, we need to
        // pass the instruction-set-features/variant as an image-compiler-option.
        // TODO: Find a better way for the instruction-set.
    #if defined(__arm__)
        constexpr const char* instruction_set = "arm";
    #elif defined(__aarch64__)
        constexpr const char* instruction_set = "arm64";
    #elif defined(__mips__) && !defined(__LP64__)
        constexpr const char* instruction_set = "mips";
    #elif defined(__mips__) && defined(__LP64__)
        constexpr const char* instruction_set = "mips64";
    #elif defined(__i386__)
        constexpr const char* instruction_set = "x86";
    #elif defined(__x86_64__)
        constexpr const char* instruction_set = "x86_64";
    #else
        constexpr const char* instruction_set = "unknown";
    #endif
        // Note: it is OK to reuse the buffer, as the values are exactly the same between
        //       * compiler-option, used for runtime compilation (DexClassLoader)
        //       * image-compiler-option, used for boot-image compilation on device
    
        // Copy the variant.
        sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
        parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
                            "--instruction-set-variant=", "-Ximage-compiler-option");
        parseCompilerOption(dex2oat_isa_variant_key, dex2oat_isa_variant,
                            "--instruction-set-variant=", "-Xcompiler-option");
        // Copy the features.
        sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
        parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
                            "--instruction-set-features=", "-Ximage-compiler-option");
        parseCompilerOption(dex2oat_isa_features_key, dex2oat_isa_features,
                            "--instruction-set-features=", "-Xcompiler-option");
    
    
        property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
        parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
    
        /* extra options; parse this late so it overrides others */
        property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
        parseExtraOpts(extraOptsBuf, NULL);
    
        /* Set the properties for locale */
        {
            strcpy(localeOption, "-Duser.locale=");
            const std::string locale = readLocale();
            strncat(localeOption, locale.c_str(), PROPERTY_VALUE_MAX);
            addOption(localeOption);
        }
    
        // Trace files are stored in /data/misc/trace which is writable only in debug mode.
        property_get("ro.debuggable", propBuf, "0");
        if (strcmp(propBuf, "1") == 0) {
            property_get("dalvik.vm.method-trace", propBuf, "false");
            if (strcmp(propBuf, "true") == 0) {
                addOption("-Xmethod-trace");
                parseRuntimeOption("dalvik.vm.method-trace-file",
                                   methodTraceFileBuf,
                                   "-Xmethod-trace-file:");
                parseRuntimeOption("dalvik.vm.method-trace-file-siz",
                                   methodTraceFileSizeBuf,
                                   "-Xmethod-trace-file-size:");
                property_get("dalvik.vm.method-trace-stream", propBuf, "false");
                if (strcmp(propBuf, "true") == 0) {
                    addOption("-Xmethod-trace-stream");
                }
            }
        }
    
        // Native bridge library. "0" means that native bridge is disabled.
        property_get("ro.dalvik.vm.native.bridge", propBuf, "");
        if (propBuf[0] == '\0') {
            ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty");
        } else if (strcmp(propBuf, "0") != 0) {
            snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX,
                     "-XX:NativeBridge=%s", propBuf);
            addOption(nativeBridgeLibrary);
        }
    
    #if defined(__LP64__)
        const char* cpu_abilist_property_name = "ro.product.cpu.abilist64";
    #else
        const char* cpu_abilist_property_name = "ro.product.cpu.abilist32";
    #endif  // defined(__LP64__)
        property_get(cpu_abilist_property_name, propBuf, "");
        if (propBuf[0] == '\0') {
            ALOGE("%s is not expected to be empty", cpu_abilist_property_name);
            return -1;
        }
        snprintf(cpuAbiListBuf, sizeof(cpuAbiListBuf), "--cpu-abilist=%s", propBuf);
        addOption(cpuAbiListBuf);
    
        // Dalvik-cache pruning counter.
        parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,
                           "-Xzygote-max-boot-retry=");
    
        /*
         * When running with debug.generate-debug-info, add --generate-debug-info to
         * the compiler options so that the boot image, if it is compiled on device,
         * will include native debugging information.
         */
        property_get("debug.generate-debug-info", propBuf, "");
        if (strcmp(propBuf, "true") == 0) {
            addOption("-Xcompiler-option");
            addOption("--generate-debug-info");
            addOption("-Ximage-compiler-option");
            addOption("--generate-debug-info");
        }
    
        /*
         * Retrieve the build fingerprint and provide it to the runtime. That way, ANR dumps will
         * contain the fingerprint and can be parsed.
         */
        parseRuntimeOption("ro.build.fingerprint", fingerprintBuf, "-Xfingerprint:");
    
        initArgs.version = JNI_VERSION_1_4;
        initArgs.options = mOptions.editArray();
        initArgs.nOptions = mOptions.size();
        initArgs.ignoreUnrecognized = JNI_FALSE;
    
        /*
         * Initialize the VM.
         *
         * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
         * If this call succeeds, the VM is ready, and we can start issuing
         * JNI calls.
         */
        if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
            ALOGE("JNI_CreateJavaVM failed\n");
            return -1;
        }
    
        return 0;
    }
    

    源码还是挺多的...要消化一下.O(∩_∩)O哈哈~

    参考

    android7.0启动zygote进程
    (连载)Android 8.0 : Android系统启动流程之zygote进程(一)

    相关文章

      网友评论

        本文标题:Android系统启动之zyogte进程

        本文链接:https://www.haomeiwen.com/subject/tzabvqtx.html