Android啟動(dòng)流程分析(2)-zygote進(jìn)程

前言

前面分析了init流程的啟動(dòng),在解析init.rc配置文件中,會(huì)執(zhí)行start zygote,然后會(huì)去解析相關(guān)的init.zygote.rc文件,在init.rc文件的頂部的import可以看出,由于操作系統(tǒng)的兼容性,有純32位,純64位,也有兼容模式的64_32,這樣會(huì)產(chǎn)生兩個(gè)zygote進(jìn)程,分別用于去fork不同位數(shù)的用戶應(yīng)用。


不同兼容版本的zygote配置文件.png

接下來(lái)就開(kāi)始分析zygote進(jìn)程的流程,以64_32位的zygote為例子分析

//#init.zygote64_32.rc
/***
 * 進(jìn)程名稱是 zygote
 * 運(yùn)行的二進(jìn)制文件在 /system/bin/app_process64
 * 啟動(dòng)參數(shù)是 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
 **/
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
    socket zygote stream 660 root system          //創(chuàng)建一個(gè) socket,名字叫zygote
    socket usap_pool_primary stream 660 root system      
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on     //onrestart 指當(dāng)前進(jìn)程重啟時(shí)執(zhí)行后面的命令
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    task_profiles ProcessCapacityHigh MaxPerformance

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
    task_profiles ProcessCapacityHigh MaxPerformance

通過(guò)對(duì)應(yīng)Android.bp文件可知道,zygote進(jìn)程的啟動(dòng),會(huì)進(jìn)入到app_main.cpp代碼,執(zhí)行對(duì)應(yīng)的main函數(shù)

//#app_main.cpp
int main(int argc, char* const argv[])
{
    // 將參數(shù) argv 放到 argv_String 字符串中,然后打印出來(lái)
    // 之前start zygote 傳入的參數(shù)是 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    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 定義于 app_main.cpp 中,繼承自 AndroidRuntime
    //就是對(duì) Android 運(yùn)行環(huán)境的一種抽象,類似于 Java 虛擬機(jī)對(duì) Java 程序的作用
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    //這兩個(gè)參數(shù)是Java 程序需要依賴的jar包,相當(dāng)于import
    const char* spaced_commands[] = { "-cp", "-classpath" };
    bool known_command = false;

    int I;
    for (i = 0; i < argc; i++) {            //解析參數(shù)的起點(diǎn)
        if (known_command == true) {        //將 space_commands 中的參數(shù)額外加入 VM
          runtime.addOption(strdup(argv[i]));
          known_command = false;
          continue;
        }

        for (int j = 0;
             j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
             ++j) {
            //比較參數(shù)是否是 spaced_commands 中的參數(shù)
          if (strcmp(argv[i], spaced_commands[j]) == 0) {
            known_command = true;
          }
        }

        //如果參數(shù)第一個(gè)字符是'-',直接跳出循環(huán),zygote啟動(dòng)的參數(shù)第一個(gè)參數(shù)就是 -Zygote,執(zhí)行到這里就會(huì)跳出循環(huán)
        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.

    //這里可以看出,通過(guò)app_main 可以啟動(dòng) zygote,system-server,普通的application進(jìn)程
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;       // app_process 的名稱改為 zygote
    String8 className;      // 啟動(dòng) apk 進(jìn)程時(shí),對(duì)應(yīng)的類名

    ++i;  // Skip unused "parent dir" argument.
    //跳過(guò)一個(gè)參數(shù),就是 -Xzygote 后面的參數(shù),也就是 、system/bin,就是所謂的parent dir
    while (i < argc) { //開(kāi)始解析參數(shù)
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) { //表示是 zygote 啟動(dòng)模式
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;  //這個(gè)值就是根據(jù)平臺(tái)參數(shù),可能是zygote64 或者 zygote
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;  //init.zygote.rc 中定義,啟動(dòng)zygote 后會(huì)啟動(dòng) system-server
        } else if (strcmp(arg, "--application") == 0) {
            application = true;  //表示是 application 啟動(dòng)模式,也就是普通的應(yīng)用程序
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);  // 進(jìn)程別名,可以自己知道進(jìn)程名
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);   // 與 --application 配置,啟動(dòng)指定的類,application 啟動(dòng)的class
            break;
        } else {
            --I;
            break;
        }
    }

    //準(zhǔn)備參數(shù)
    Vector<String8> args;
    if (!className.isEmpty()) {  //className 不為空,說(shuō)明是 application 啟動(dòng)模式
        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 啟動(dòng)模式
        // We're in zygote mode.
        maybeCreateDalvikCache();  //創(chuàng)建dalvik 的緩存目錄并定義權(quán)限

        if (startSystemServer) {   //增加 start-system-server 參數(shù)
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];  //獲取對(duì)應(yīng)平臺(tái)的 abi 信息
        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=");  //參數(shù)需要指定 abi
        abiFlag.append(prop);
        args.add(abiFlag);              // 加入 --abi-list = 參數(shù)

        for (; i < argc; ++i) {
            args.add(String8(argv[i]));     //將剩下的參數(shù)加入 args 
        }
    }

    if (!niceName.isEmpty()) {   //將 app_process 的進(jìn)程名,替換為niceName
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {   //調(diào)用 Runtime 的start 函數(shù),啟動(dòng) zygoteInit
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        //非zygote啟動(dòng)方式進(jìn)入這個(gè)分支
        //如果是 application 啟動(dòng)模式,則加入 RuntimeInit
        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.");
    }
}

小結(jié)

app_main.cpp的代碼流程小結(jié)一下

  • 初始化AndroidRuntime
  • strcmp(arg, "--zygote") 設(shè)置為zygote啟動(dòng)模式
  • args.add(String8("start-system-server"))給start函數(shù)的參數(shù)args賦值
  • runtime.start("com.android.internal.os.ZygoteInit", args, zygote) 啟動(dòng)zygoteInit

從Android的系統(tǒng)架構(gòu)來(lái)看,硬件抽象層上面和JNI同級(jí)別的有一個(gè)Android runtime,ART的的初始化也是在zygote的啟動(dòng)流程中,接著就進(jìn)入了runtime的start()方法

//#AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
   
    static const String8 startSystemServer("start-system-server");
    // Whether this is the primary zygote, meaning the zygote which will fork system server.
    bool primary_zygote = false;

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);  //初始化 JNI,加載 libart.so
    JNIEnv* env;

    //創(chuàng)建虛擬機(jī),其中大多數(shù)參數(shù)有系統(tǒng)屬性決定,最終startVm 利用 JNI_CreateJavaVM 創(chuàng)建虛擬機(jī)
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }

    //回調(diào) AppRuntime 的 onVmCreated 函數(shù)
    //對(duì)于 zygote 進(jìn)程的啟動(dòng)流程而言,無(wú)實(shí)際操作,表示虛擬機(jī)創(chuàng)建完成,里面是空實(shí)現(xiàn)
    onVmCreated(env);

    //注冊(cè) JNI 函數(shù)
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    //替換string為實(shí)際路徑,將"com.android.internal.os.ZygoteInit" 替換為 “com/android/internal/os/ZygoteInit”
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName); //找到class文件
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V"); //通過(guò)反射找到ZygoteInit 的 main 函數(shù)
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);  //調(diào)用ZygoteInit的main()函數(shù)

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

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)  //退出當(dāng)前線程
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)              //創(chuàng)建一個(gè)線程,該線程會(huì)等待所有子線程結(jié)束后關(guān)閉虛擬機(jī)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

int AndroidRuntime::startReg(JNIEnv* env)
{
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    return 0;
}

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
                        return -1;
        }
    }
    return 0;
}

static const RegJNIRec gRegJNI[] = {
        REG_JNI(register_com_android_internal_os_RuntimeInit),
        REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
        REG_JNI(register_android_os_SystemClock),
                ......
}

struct RegJNIRec {
      int (*mProc)(JNIEnv*);
};

從源代碼中找到主要的流程

  • startVm 創(chuàng)建虛擬機(jī)
  • startReg 注冊(cè)JNI方法
  • env->CallStaticVoidMethod 使用JNI調(diào)用ZygoteInit 的main函數(shù),進(jìn)入java層

這部分就是zygote的c++代碼的主要業(yè)務(wù),會(huì)創(chuàng)建虛擬機(jī),也會(huì)注冊(cè)JNI方法,注冊(cè)JNI方法就是類似的一個(gè)方法名對(duì)應(yīng)的關(guān)聯(lián)代理,在AndroidRuntim.cpp文件中,就會(huì)查到相關(guān)的jni調(diào)用的函數(shù)指向,處理完這些,就會(huì)進(jìn)入java層的zygote流程

小結(jié)

從上面的流程可以看出,在Zygote進(jìn)程中通過(guò)startVm方法啟動(dòng)了虛擬機(jī),后續(xù)應(yīng)用進(jìn)程通過(guò)zygote孵化拷貝fork出新的進(jìn)程,就會(huì)復(fù)制zygote中的虛擬機(jī),所以每個(gè)應(yīng)用進(jìn)程會(huì)有自己獨(dú)立的虛擬機(jī),虛擬機(jī)的主要功能就是實(shí)現(xiàn)進(jìn)程的內(nèi)存管理(堆區(qū),方法區(qū),棧之類的),每個(gè)進(jìn)程獨(dú)立管理自己的內(nèi)存,遇到各種內(nèi)存問(wèn)題導(dǎo)致進(jìn)程崩潰而相互之間不會(huì)影響,做到了進(jìn)程間的隔離

Java層Zygote流程

上面的流程還是在c++代碼中,通過(guò)反射執(zhí)行到了ZygoteInit.main(),進(jìn)入了Java層的邏輯

//#ZygoteInit.java  
public static void main(String argv[]) {
        ZygoteServer zygoteServer = null; //

        ZygoteHooks.startZygoteNoThreadCreation(); //調(diào)用native函數(shù),確保當(dāng)前沒(méi)有其他線程在運(yùn)行,主要出于安全的考慮

        Runnable caller;
        try {
            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            //解析參數(shù),得到上述變量的值
            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)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[I]);
                }
            }

            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
                preload(bootTimingsTraceLog);     //默認(rèn)情況,預(yù)加載信息
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            }

            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);  //fork systemserver

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }

            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);  //zygote 進(jìn)程進(jìn)入無(wú)限循環(huán),處理請(qǐng)求
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

    }

通過(guò)上述源碼,zygote的Java層啟動(dòng)流程梳理一下

  • preload(bootTimingsTraceLog) 預(yù)加載資源,加快后續(xù)進(jìn)程的啟動(dòng),應(yīng)用進(jìn)程也是從zygote進(jìn)程孵化來(lái)的,一些系統(tǒng)的默認(rèn)資源在zygote進(jìn)行預(yù)加載,加快后續(xù)進(jìn)程孵化啟動(dòng)的速度
  • zygoteServer = new ZygoteServer(isPrimaryZygote) 實(shí)例化socket
  • Runnable r = forkSystemServer() 啟動(dòng)systemserver 進(jìn)程,AMS
  • caller = zygoteServer.runSelectLoop(abiList) 死循環(huán),接收AMS傳過(guò)來(lái)的信息

到此Zygote進(jìn)程的啟動(dòng)流程結(jié)束,zygote進(jìn)程會(huì)去啟動(dòng)systemserver進(jìn)程,這個(gè)進(jìn)程跟各種系統(tǒng)服務(wù)有關(guān)系,zygote會(huì)通過(guò)socket的通信方式,接收其他進(jìn)程的請(qǐng)求,去孵化應(yīng)用進(jìn)程

總結(jié)

zygote進(jìn)程的啟動(dòng)分為native層和Java層

native層:

  • 會(huì)去初始化運(yùn)行環(huán)境,創(chuàng)建jvm Android 虛擬機(jī)-AndroidRuntime ART
  • 注冊(cè)JNI
  • 調(diào)用zygoteInit.main進(jìn)入java層

java層:

  • 預(yù)加載系統(tǒng)資源,加快后續(xù)應(yīng)用進(jìn)程的啟動(dòng)速度
  • socket 跨進(jìn)程通信方案,接收其他進(jìn)程的消息
  • 循環(huán)等待消息

zygote的流程走完了,下一篇開(kāi)始分析systemserver的流程了

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

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

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