zygote進(jìn)程及init進(jìn)程對(duì)zygote進(jìn)程的啟動(dòng)

android源碼學(xué)習(xí)目錄

1.介紹

zygote進(jìn)程是一個(gè)孵化器,zygote進(jìn)程啟動(dòng)時(shí)會(huì)創(chuàng)建Android 中ART虛擬機(jī)。SystemServer進(jìn)程,應(yīng)用程序進(jìn)程以及運(yùn)行系統(tǒng)的關(guān)鍵服務(wù)進(jìn)程都是通過fock(復(fù)制進(jìn)程)zygote自身來(lái)完成的,所以我們也叫它孵化器進(jìn)程,因?yàn)閟ystemserver等進(jìn)程是通過fock zygote來(lái)完成的,所以zygote中的ART虛擬機(jī)也會(huì)帶入到SystemServer等進(jìn)程。這也就是我們通常所說(shuō)的Android應(yīng)用一個(gè)應(yīng)用一個(gè)虛擬機(jī)。

2.init進(jìn)程對(duì)zygote的啟動(dòng)

上文中我們介紹了init進(jìn)程對(duì)init.rc文件的解析和action的執(zhí)行,zygote是一個(gè)服務(wù),其配置與開始執(zhí)行也是init.rc文件的一部分,它通過import插入到init.rc文件中,根據(jù)不同的系統(tǒng)解析不同的文件,位置在/system/core/rootdir/init.zygotexx.rc, xx是更具不同系統(tǒng)區(qū)分的,有x86有x64, init.zygote64.rc的解析和action一樣,他的解析是通過Parse解析入口添加的ServiceParse類進(jìn)程的,同樣有ServiceManager來(lái)進(jìn)行保存,通過init進(jìn)程main函數(shù) restart_processes(); 來(lái)啟動(dòng)zygote服務(wù)。

2.1zygote服務(wù)配置

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

從上面可以知道 service是通知init進(jìn)程創(chuàng)建名為zygote的進(jìn)程,進(jìn)程路徑為/system/bin/app_process64,下面的為zygote服務(wù)的參數(shù),class為main.

2.2,init進(jìn)程對(duì)zygote的啟動(dòng)

我們知道init.rc解析后會(huì)逐個(gè)執(zhí)行action,init.rc文件中的一個(gè)action有如下配置

on nonencrypted
    class_start main  //1
    class_start late_start

這個(gè)action的command有class_start main,這就是要啟動(dòng)那些classname為main的服務(wù),zygote服務(wù)的classname就為main,所以也會(huì)啟動(dòng)。通過命令與函數(shù)的綁定我們了解action的class_start執(zhí)行的函數(shù)就是/system/core/init/builtins.cpp中的do_class_start函數(shù)。

///system/core/init/builtins.cpp
static int do_class_start(const std::vector<std::string>& args) {
    ServiceManager::GetInstance().
        ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
    return 0;
}

代碼執(zhí)行的邏輯:從ServiceManager保存的所有之前解析的Service表中找到classname為main的服務(wù),讓service執(zhí)行StartNotDisabled()函數(shù)

// /system/core/init/service.cpp
bool Service::StartIfNotDisabled() {
    if (!(flags_ & SVC_DISABLED)) {  //判斷init.rc配置,init.rc并沒有設(shè)置disabled選項(xiàng)
        return Start();  //服務(wù)啟動(dòng)
    } else {
        flags_ |= SVC_DISABLED_START;
    }
    return true;
}

更具配置來(lái)判斷是否啟動(dòng)服務(wù),這個(gè)配置啟動(dòng)是是否允許這個(gè)服務(wù)重啟,允許則設(shè)置服務(wù)終止時(shí)會(huì)通過進(jìn)程終止信號(hào)經(jīng)過層層處理找到這個(gè)進(jìn)程,清除這個(gè)進(jìn)程的所有信息,并重啟進(jìn)程。

bool Service::Start() {
    // Starting a service removes it from the disabled or reset state and
    // immediately takes it out of the restarting state if it was in there.
    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));

    // Running processes require no additional work --- if they're in the
    // process of exiting, we've ensured that they will immediately restart
    // on exit, unless they are ONESHOT.
    //如果服務(wù)以啟動(dòng)則不做操作。
    if (flags_ & SVC_RUNNING) {
        return false;
    }

    bool needs_console = (flags_ & SVC_CONSOLE);
    if (needs_console) {
        if (console_.empty()) {
            console_ = default_console;
        }
    ...
    //判斷要啟動(dòng)的service所對(duì)應(yīng)的執(zhí)行文件是否存在,不存在則不執(zhí)行
    struct stat sb;
    if (stat(args_[0].c_str(), &sb) == -1) {
        PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'";
        flags_ |= SVC_DISABLED;
        return false;
    }

    std::string scon;
    if (!seclabel_.empty()) {
        scon = seclabel_;
    } else {
        LOG(INFO) << "computing context for service '" << name_ << "'";
        scon = ComputeContextFromExecutable(name_, args_[0]);
        if (scon == "") {
            return false;
        }
    }

    LOG(INFO) << "starting service '" << name_ << "'...";

    pid_t pid = -1;
    if (namespace_flags_) {
        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
    } else {
        pid = fork();  //1 重點(diǎn),通過fock來(lái)創(chuàng)建子進(jìn)程,
    }

    if (pid == 0) {
        umask(077);

     ````
        // As requested, set our gid, supplemental gids, uid, context, and
        // priority. Aborts on failure.
        SetProcessAttributes();

        std::vector<char*> strs;
        ExpandArgs(args_, &strs);
        if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {   //2 重點(diǎn),開啟子進(jìn)程執(zhí)行。
            PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
        }

        _exit(127);
    }

   ...
    NotifyStateChange("running");
    return true;
}

start()函數(shù)比較長(zhǎng),這里我們只關(guān)心幾點(diǎn)就可以,其他的都是一些參數(shù)和console的操作。

  • 注釋1處:這里是重點(diǎn),init進(jìn)程啟動(dòng)子進(jìn)程服務(wù)都是通過fock函數(shù)來(lái)創(chuàng)建一個(gè)子進(jìn)程來(lái)完成的,也就是說(shuō)init啟動(dòng)的service都是一個(gè)進(jìn)程,zygote也是一個(gè)進(jìn)成。
  • 注釋2處:這里是真正開始執(zhí)行進(jìn)程,也就是告訴這個(gè)進(jìn)程要執(zhí)行什么,也就是zygote進(jìn)程在這里開始執(zhí)行。

\color{#ea4335}{注意:}init進(jìn)程通過fock后與execve之后就是創(chuàng)建新子進(jìn)程來(lái)執(zhí)行了,也就是說(shuō)下面介紹的--2.3啟動(dòng)zygote過程-- 其實(shí)也是zygote進(jìn)程的一部分,只是沒有執(zhí)行好進(jìn)程的main函數(shù)。

2.3啟動(dòng)zygote過程

execve(strs[0], (char) &strs[0], (char) ENV)函數(shù)主要是init進(jìn)程通過調(diào)動(dòng)app_main.cpp的main函數(shù)中的AppRuntime的start方法來(lái)執(zhí)行啟動(dòng)zygote的,

//位置/framework/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
   ....  //做了很多配置和參數(shù)操作
   
    while (i < argc) {
        const char* arg = argv[i++];
        //下面根據(jù)不同的線程設(shè)置不同的標(biāo)記位
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;  //如果是zygote進(jìn)程,則zygote為true
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true; //如果是SystemServer進(jìn)程,則SystemServer為true
        } else if (strcmp(arg, "--application") == 0) {
            application = true; //如果是application進(jìn)程,則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 (zygote) {
        //如果運(yùn)行在zygote進(jìn)程中則通過runtim開始啟動(dòng)進(jìn)程
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
      //其他的更具classname來(lái)執(zhí)行進(jìn)程。
        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.");
    }

這里通過分析組合各個(gè)參數(shù)根據(jù)屬性來(lái)啟動(dòng)這個(gè)進(jìn)程,zygote就是這樣啟動(dòng)的, runtime.start("com.android.internal.os.ZygoteInit", args, zygote);是執(zhí)行的AndroidRuntime.cpp中的代碼。

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    .....


    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {  //啟動(dòng)Java虛擬機(jī)
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {  //向Java虛擬機(jī)注冊(cè)JNI方法,這樣才能使Java與c++互調(diào)
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    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);
    //從上文我們知道classname為傳入的參數(shù)為"com.android.internal.os.ZygoteInit",將classname轉(zhuǎn)換為Java中的String 字符串。
    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);
    }

    //替換classnam中的.為/這樣jvm才能識(shí)別。  
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        //找到classname中的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)用classname的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");
}

AndroidRuntime.start方法做了不少工作,主要的工作就是創(chuàng)建Java虛擬機(jī),注入jni方法,解析參數(shù)classname為jvm能識(shí)別的classname, 找到classname中的main方法并執(zhí)行,這時(shí)我們所熟悉的Java進(jìn)程中的main方法開始執(zhí)行了,也就是zygote的main方法開始執(zhí)行了。

最后編輯于
?著作權(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ù)。

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