Zygote启动-代码阅读

概述

zygote是android 系统的一个孵化器,可通过它分裂一个个子进程,为了理解zygote工作原理,这里做些记录,方便后续查阅和修正,加深理解。

基于andoid 4.4阅读

init启动zygote

init作为linux 用户空间第一个进程,主要目的是通过解析init.rc来启动android一系列的进程服务。其中就有zygote

关于解析规则可参考源码system/core/init/readme.txt

zygote的启动配置

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class core
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

参考用例:

服务是初始化启动和(可选)重新启动的程序,当他们退出时。 服务采取以下形式:
service <name> <pathname> [ <argument> ]*
   <option>
   <option>
   ...

name : 进程的名字zygote
pathname:执行文件路径 /system/bin/app_process
argument: 执行的参数 -Xzygote /system/bin --zygote --start-system-server

zygote程序入口

/system/bin/app_process的进程编译文件路径:frameworks/base/cmds/app_process/app_main.cpp
通过上面init.rc的配置我们知道argv参数有
-Xzygote
/system/bin
–zygote
–start-system-server

int main(int argc, char* const argv[])
{
    // These are global variables in ProcessState.cpp
    mArgC = argc;
    mArgV = argv;

    mArgLen = 0;
    for (int i=0; i<argc; i++) {
        mArgLen += strlen(argv[i]) + 1;
    }
    mArgLen--;

    AppRuntime runtime;
    const char* argv0 = argv[0];

    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    // Everything up to '--' or first non '-' arg goes to the vm

    int i = runtime.addVmArguments(argc, argv);

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    const char* parentDir = NULL;
    const char* niceName = NULL;
    const char* className = NULL;
    while (i < argc) {
        const char* arg = argv[i++];
        if (!parentDir) {
            parentDir = arg;
        } else if (strcmp(arg, "--zygote") == 0) {//满足条件
            zygote = true;
            niceName = "zygote";
        } 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 = arg + 12;
        } else {
            className = arg;
            break;
        }
    }
//待循环获取参数后
//zygote = true;  niceName = "zygote";startSystemServer = true;
    if (niceName && *niceName) {
        setArgv0(argv0, niceName);
        set_process_name(niceName);
    }

    runtime.mParentDir = parentDir;

    if (zygote) {
        //会通过AndrodRuntime.start 反射启动java类ZygoteInit的
        //静态方法main并带参数 start-system-server
        runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer ? "start-system-server" : "");
    } else if (className) {
        // Remainder of args get passed to startup class main()
        runtime.mClassName = className;
        runtime.mArgC = argc - i;
        runtime.mArgV = argv + i;
        runtime.start("com.android.internal.os.RuntimeInit",
                application ? "application" : "tool");
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

具体start过程可以查看拿AndroidRuntime.cpp

/ *
  *启动Android运行时。 这涉及启动虚拟机并在" className"命名的类中
  *调用" static void main(String [] args)"方法。
  *
  *向主函数传递两个参数,即类名和指定的选项字符串。
  * /
void AndroidRuntime::start(const char* className, const char* options)
{
    ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
            className != NULL ? className : "(unknown)");

     //'startSystemServer == true'表示运行时已过时,不再从init.rc中运行,
     //因此我们在此处打印启动启动事件。
    if (strcmp(options, "start-system-server") == 0) {//满足条件
        /*在启动顺序中跟踪我们的进度 */
        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);
    }

    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

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

    /*
     * 注册android函数。
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

     / *
      *我们想用包含参数的String数组调用main()*目前,我们有两个参数,即类名和选项字符串。
      *创建一个数组来保存它们。
      * /
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;
    jstring optionsStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(2, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
    optionsStr = env->NewStringUTF(options);
    env->SetObjectArrayElement(strArray, 1, optionsStr);

    / *
      *启动VM。 该线程成为VM的主线程,并将
      *在虚拟机退出之前不返回。
      * /
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    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");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            //反射的方式静态启动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");
}

启动后会在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
main运行

    public static void main(String argv[]) {
        try {
            // 开始分析zygote初始化。
            SamplingProfilerIntegration.start();

            registerZygoteSocket();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            //预加载资源和类
            preload();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());

            // 完成概要分析zygote初始化。
            SamplingProfilerIntegration.writeZygoteSnapshot();

            // 启动后进行初始gc清理
            gc();

            // 禁用跟踪,以便分叉进程不会从Zygote继承陈旧的跟踪标记。
            Trace.setTracingEnabled(false);

            // 如果需要,请直接从Zygote启动系统服务器
            if (argv.length != 2) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }

            if (argv[1].equals("start-system-server")) {
                startSystemServer();
            } else if (!argv[1].equals("")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }

            Log.i(TAG, "Accepting command socket connections");

            //运行循环读取socket信息,用于fork分裂子进程
            runSelectLoop();

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

此时zygote已经启动完毕,后续是systemserver启动,在startSystemServer这个函数中通知启动android 的一系列系统服务。

zygote启动应用

时序图
在这里插入图片描述

  1. 从左边开始init启动,在通过解析init.rc 启动zygote;
  2. zygote内部初始化完毕后,启动systemserver,也是通过socket 通讯发送给zygote,解析后fork一个子进程,在启动SystemServer.main
  3. 在systemserver中会初始化ActivityManagerService,然后等systemReady 所有服务启动完成,便会用socket 通知zygote fork一个launcher app
  4. 在launcher 点击一个应用会使用startActivity启动一个app,也会同样通知zygote fork一个app
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月夜持剑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值