Android系統(tǒng)從init進程到Launcher(二)

前言

Android 系統(tǒng)中,DVMART、應(yīng)用程序進程以及運行系統(tǒng)的關(guān)鍵服務(wù)的 SystemServer 進程都是由 Zygote 進程來創(chuàng)建的。它通過 fock 的形式來創(chuàng)建應(yīng)用程序進程和 SystemServer 進程,由于 Zygote 進程在啟動時會創(chuàng)建 DVMART,因此通過 fock 而創(chuàng)建的應(yīng)用程序進程和 SystemServer 進程可以在內(nèi)部獲取一個 DVM 或者 ART 的實例副本。

Zygote 進程任務(wù)

  1. 創(chuàng)建 AppRuntime 并調(diào)用其start 方法,啟動 Zygote 進程
  2. 創(chuàng)建 Java 虛擬機并為 Java 虛擬機注冊 JNI 方法
  3. 通過 JNI 調(diào)用 Zygote 的 main 函數(shù)進入 Zygote 的 Java 框架層
  4. 通過 registerZygoteSocket 方法創(chuàng)建服務(wù)器端 Socket,并通過 runSelectLoop 方法等待AMS 的請求來創(chuàng)建新的應(yīng)用程序進程
  5. 啟動 SystemServer 進程

Zygote 啟動腳本

init.rc 文件中采用了 Import 類型語句引入 Zygote 啟動腳本:

import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
// ro.zygote 由硬件來決定引入的是32位還是64位
import /init.${ro.zygote}.rc

on early-init
    # Set init and its forked children's oom_adj.
    write /proc/1/oom_score_adj -1000
......

這里我們以 64 位程序為例:/system/core/rootdir/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 reserved_disk
    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 進程名稱為 zygote,執(zhí)行程序為 app_process,classnamemain ,當 server 重啟的時候,會重啟 audioserver、cameraserver、media、netd、wificond 進程;而 app_process 進程對應(yīng)的源文件路徑在 /frameworks/base/cmds/app_process/app_main.cpp

init 啟動 Zygote 時主要是調(diào)用 app_main.cppmain 函數(shù)中的 AppRuntimestart 方法來啟動 Zygote 進程,其時序圖如下:

1. app_main.cpp # main函數(shù)源碼分析

/frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
    
    // argv = “/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server”

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    argc--; // 跳過第一個參數(shù)/system/bin/app_precess
    argv++;

    
    // -Xzygote為虛擬機參數(shù),在啟動虛擬機是傳遞到虛擬機
    int i;
    for (i = 0; i < argc; i++) {
        if (known_command == true) {
          runtime.addOption(strdup(argv[i]));
          // The static analyzer gets upset that we don't ever free the above
          // string. Since the allocation is from main, leaking it doesn't seem
          // problematic. NOLINTNEXTLINE
          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]));

    }

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // 跳過 /system/bin參數(shù)
    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;
    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 {
        // 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]));
        }
    }

    // 修改線程名為zygote
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    // 根據(jù)得到的參數(shù)調(diào)用com.android.internal.os.ZygoteInit
    // args這個vector中包含兩個成員,args[0] = “start-system-server”
    // args[1] = “—abi-list=xxx” xxx代碼的是CPU的結(jié)構(gòu),比如armeabi-v7a, arm64-v8a
    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.");
    }
}

根據(jù)前面所述,Zygote 進程是通過 fock 自身來創(chuàng)建子進程的,這樣 Zygote 進程和由它所創(chuàng)建的子進程都會進入到 app_main.cppmain 函數(shù)中,因此在 注釋① 處會做判斷當前是運行在哪個進程中。
注釋② 處判斷 zygotetrue ,則說明當前運行在 Zygote 進程中,就會調(diào)用 AppRuntimestart 函數(shù)。

AppRuntime類的聲明和實現(xiàn)都在App_main.cpp中,它是從AndroidRuntime類派生出來的,代碼如下:

frameworks/base/core/jni/AndroidRuntime.cpp

// className = "com.android.internal.os.ZygoteInit", options包含兩個string8成員
// args[0] = “start-system-server” args[1] = “—abi-list=xxx”, zygote = true
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    static const String8 startSystemServer("start-system-server");

    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }

    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }

    // 創(chuàng)建并啟動虛擬機
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 設(shè)置虛擬機的JNI環(huán)境
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    // 調(diào)用JNI方法調(diào)用com.android.internal.os.ZygoteInit中的main方法
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    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);
    }

    // 至此,strArray中包含三個成員,分別是 
    // strArray[0] = “com.android.internal.os.ZygoteInit”
    // strArray[1] = “start-system-server”
    // strArray[2] = “—abi-list=xxx”
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    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 {
            // 調(diào)用ZygoteInit的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

由于當前的運行邏輯在 Native 中,而 ZygoteInit 是用Java語言編寫的,所以在 注釋① 處需要使用 JNI 方式調(diào)用 ZygoteInitmain 方法,由此 Zygote 便進入了 Java 框架層,換而言之 Zygote 開創(chuàng)了 Java 框架層。代碼如下:

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

public static void main(String argv[]) {

        ZygoteServer zygoteServer = new ZygoteServer();

        try {
            
            RuntimeInit.enableDdms();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;

            // 解析傳入的argv參數(shù),其中argv就是AndroidRuntime.cpp中的strArray
            // strArray[0] = “com.android.internal.os.ZygoteInit”
            // strArray[1] = “start-system-server”
            // strArray[2] = “—abi-list=xxx”

            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)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            // 創(chuàng)建一個 Server 端的Socket,socketName的值為 “zygote”  注釋①
            zygoteServer.registerServerSocketFromEnv(socketName);
            // 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());

                //預(yù)加載類和相應(yīng)資源
                preload(bootTimingsTraceLog);
                
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }

            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");

            //強制執(zhí)行g(shù)c進行一次垃圾回收
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            ...

            if (startSystemServer) {

                // 啟動SystemServer進程  注釋②
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);

              
                if (r != null) {
                    r.run();
                    return;
                }
            }

            // 等待 AMS 請求   注釋③
            caller = zygoteServer.runSelectLoop(abiList);

        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }

    
        if (caller != null) {
            caller.run();
        }
    }

注釋① 處通過 registerServerSocket 方法創(chuàng)建一個 Server 端的 Socket ,這個 name“zygote”Socket 用于等待 ActivityManagerService 請求 Zygote 來創(chuàng)建新的而應(yīng)用程序。在 注釋② 處啟動 SystemServer 進程,這樣系統(tǒng)的服務(wù)也會由 SystemServer 進程啟動起來。注釋③ 調(diào)用 ZygoteServer 的 runSelectLoop 方法等待 AMS 請求創(chuàng)建新的應(yīng)用程序進程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容