zygote进程及init进程对zygote进程的启动

android源码学习目录

1.介绍

zygote进程是一个孵化器,zygote进程启动时会创建Android 中ART虚拟机。SystemServer进程,应用程序进程以及运行系统的关键服务进程都是通过fock(复制进程)zygote自身来完成的,所以我们也叫它孵化器进程,因为systemserver等进程是通过fock zygote来完成的,所以zygote中的ART虚拟机也会带入到SystemServer等进程。这也就是我们通常所说的Android应用一个应用一个虚拟机。

2.init进程对zygote的启动

上文中我们介绍了init进程对init.rc文件的解析和action的执行,zygote是一个服务,其配置与开始执行也是init.rc文件的一部分,它通过import插入到init.rc文件中,根据不同的系统解析不同的文件,位置在/system/core/rootdir/init.zygotexx.rc, xx是更具不同系统区分的,有x86有x64, init.zygote64.rc的解析和action一样,他的解析是通过Parse解析入口添加的ServiceParse类进程的,同样有ServiceManager来进行保存,通过init进程main函数 restart_processes(); 来启动zygote服务。

2.1zygote服务配置

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进程创建名为zygote的进程,进程路径为/system/bin/app_process64,下面的为zygote服务的参数,class为main.

2.2,init进程对zygote的启动

我们知道init.rc解析后会逐个执行action,init.rc文件中的一个action有如下配置

on nonencrypted
    class_start main  //1
    class_start late_start

这个action的command有class_start main,这就是要启动那些classname为main的服务,zygote服务的classname就为main,所以也会启动。通过命令与函数的绑定我们了解action的class_start执行的函数就是/system/core/init/builtins.cpp中的do_class_start函数。

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

代码执行的逻辑:从ServiceManager保存的所有之前解析的Service表中找到classname为main的服务,让service执行StartNotDisabled()函数

// /system/core/init/service.cpp
bool Service::StartIfNotDisabled() {
    if (!(flags_ & SVC_DISABLED)) {  //判断init.rc配置,init.rc并没有设置disabled选项
        return Start();  //服务启动
    } else {
        flags_ |= SVC_DISABLED_START;
    }
    return true;
}

更具配置来判断是否启动服务,这个配置启动是是否允许这个服务重启,允许则设置服务终止时会通过进程终止信号经过层层处理找到这个进程,清除这个进程的所有信息,并重启进程。

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.
    //如果服务以启动则不做操作。
    if (flags_ & SVC_RUNNING) {
        return false;
    }

    bool needs_console = (flags_ & SVC_CONSOLE);
    if (needs_console) {
        if (console_.empty()) {
            console_ = default_console;
        }
    ...
    //判断要启动的service所对应的执行文件是否存在,不存在则不执行
    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 重点,通过fock来创建子进程,
    }

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

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

        std::vector strs;
        ExpandArgs(args_, &strs);
        if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {   //2 重点,开启子进程执行。
            PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
        }

        _exit(127);
    }

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

start()函数比较长,这里我们只关心几点就可以,其他的都是一些参数和console的操作。

  • 注释1处:这里是重点,init进程启动子进程服务都是通过fock函数来创建一个子进程来完成的,也就是说init启动的service都是一个进程,zygote也是一个进成。
  • 注释2处:这里是真正开始执行进程,也就是告诉这个进程要执行什么,也就是zygote进程在这里开始执行。

init进程通过fock后与execve之后就是创建新子进程来执行了,也就是说下面介绍的--2.3启动zygote过程-- 其实也是zygote进程的一部分,只是没有执行好进程的main函数。

2.3启动zygote过程

execve(strs[0], (char) &strs[0], (char) ENV)函数主要是init进程通过调动app_main.cpp的main函数中的AppRuntime的start方法来执行启动zygote的,

//位置/framework/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
   ....  //做了很多配置和参数操作
   
    while (i < argc) {
        const char* arg = argv[i++];
        //下面根据不同的线程设置不同的标记位
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;  //如果是zygote进程,则zygote为true
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true; //如果是SystemServer进程,则SystemServer为true
        } else if (strcmp(arg, "--application") == 0) {
            application = true; //如果是application进程,则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) {
        //如果运行在zygote进程中则通过runtim开始启动进程
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
      //其他的更具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.");
    }

这里通过分析组合各个参数根据属性来启动这个进程,zygote就是这样启动的, runtime.start("com.android.internal.os.ZygoteInit", args, zygote);是执行的AndroidRuntime.cpp中的代码。

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


    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {  //启动Java虚拟机
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {  //向Java虚拟机注册JNI方法,这样才能使Java与c++互调
        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为传入的参数为"com.android.internal.os.ZygoteInit",将classname转换为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才能识别。  
    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 {
            //在这里调用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方法做了不少工作,主要的工作就是创建Java虚拟机,注入jni方法,解析参数classname为jvm能识别的classname, 找到classname中的main方法并执行,这时我们所熟悉的Java进程中的main方法开始执行了,也就是zygote的main方法开始执行了。

你可能感兴趣的:(zygote进程及init进程对zygote进程的启动)