Android启动流程分析(2)-zygote进程

前言

前面分析了init流程的启动,在解析init.rc配置文件中,会执行start zygote,然后会去解析相关的init.zygote.rc文件,在init.rc文件的顶部的import可以看出,由于操作系统的兼容性,有纯32位,纯64位,也有兼容模式的64_32,这样会产生两个zygote进程,分别用于去fork不同位数的用户应用。


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

接下来就开始分析zygote进程的流程,以64_32位的zygote为例子分析

//#init.zygote64_32.rc
/***
 * 进程名称是 zygote
 * 运行的二进制文件在 /system/bin/app_process64
 * 启动参数是 -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          //创建一个 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 指当前进程重启时执行后面的命令
    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

通过对应Android.bp文件可知道,zygote进程的启动,会进入到app_main.cpp代码,执行对应的main函数

//#app_main.cpp
int main(int argc, char* const argv[])
{
    // 将参数 argv 放到 argv_String 字符串中,然后打印出来
    // 之前start zygote 传入的参数是 -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
    //就是对 Android 运行环境的一种抽象,类似于 Java 虚拟机对 Java 程序的作用
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    //这两个参数是Java 程序需要依赖的jar包,相当于import
    const char* spaced_commands[] = { "-cp", "-classpath" };
    bool known_command = false;

    int I;
    for (i = 0; i < argc; i++) {            //解析参数的起点
        if (known_command == true) {        //将 space_commands 中的参数额外加入 VM
          runtime.addOption(strdup(argv[i]));
          known_command = false;
          continue;
        }

        for (int j = 0;
             j < static_cast(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
             ++j) {
            //比较参数是否是 spaced_commands 中的参数
          if (strcmp(argv[i], spaced_commands[j]) == 0) {
            known_command = true;
          }
        }

        //如果参数第一个字符是'-',直接跳出循环,zygote启动的参数第一个参数就是 -Zygote,执行到这里就会跳出循环
        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.

    //这里可以看出,通过app_main 可以启动 zygote,system-server,普通的application进程
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;       // app_process 的名称改为 zygote
    String8 className;      // 启动 apk 进程时,对应的类名

    ++i;  // Skip unused "parent dir" argument.
    //跳过一个参数,就是 -Xzygote 后面的参数,也就是 、system/bin,就是所谓的parent dir
    while (i < argc) { //开始解析参数
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) { //表示是 zygote 启动模式
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;  //这个值就是根据平台参数,可能是zygote64 或者 zygote
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;  //init.zygote.rc 中定义,启动zygote 后会启动 system-server
        } else if (strcmp(arg, "--application") == 0) {
            application = true;  //表示是 application 启动模式,也就是普通的应用程序
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);  // 进程别名,可以自己知道进程名
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);   // 与 --application 配置,启动指定的类,application 启动的class
            break;
        } else {
            --I;
            break;
        }
    }

    //准备参数
    Vector args;
    if (!className.isEmpty()) {  //className 不为空,说明是 application 启动模式
        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 启动模式
        // We're in zygote mode.
        maybeCreateDalvikCache();  //创建dalvik 的缓存目录并定义权限

        if (startSystemServer) {   //增加 start-system-server 参数
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];  //获取对应平台的 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=");  //参数需要指定 abi
        abiFlag.append(prop);
        args.add(abiFlag);              // 加入 --abi-list = 参数

        for (; i < argc; ++i) {
            args.add(String8(argv[i]));     //将剩下的参数加入 args 
        }
    }

    if (!niceName.isEmpty()) {   //将 app_process 的进程名,替换为niceName
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {   //调用 Runtime 的start 函数,启动 zygoteInit
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        //非zygote启动方式进入这个分支
        //如果是 application 启动模式,则加入 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.");
    }
}

小结

app_main.cpp的代码流程小结一下

  • 初始化AndroidRuntime
  • strcmp(arg, "--zygote") 设置为zygote启动模式
  • args.add(String8("start-system-server"))给start函数的参数args赋值
  • runtime.start("com.android.internal.os.ZygoteInit", args, zygote) 启动zygoteInit

从Android的系统架构来看,硬件抽象层上面和JNI同级别的有一个Android runtime,ART的的初始化也是在zygote的启动流程中,接着就进入了runtime的start()方法

//#AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector& 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;

    //创建虚拟机,其中大多数参数有系统属性决定,最终startVm 利用 JNI_CreateJavaVM 创建虚拟机
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }

    //回调 AppRuntime 的 onVmCreated 函数
    //对于 zygote 进程的启动流程而言,无实际操作,表示虚拟机创建完成,里面是空实现
    onVmCreated(env);

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

    //替换string为实际路径,将"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"); //通过反射找到ZygoteInit 的 main 函数
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);  //调用ZygoteInit的main()函数

#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");
}

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 创建虚拟机
  • startReg 注册JNI方法
  • env->CallStaticVoidMethod 使用JNI调用ZygoteInit 的main函数,进入java层

这部分就是zygote的c++代码的主要业务,会创建虚拟机,也会注册JNI方法,注册JNI方法就是类似的一个方法名对应的关联代理,在AndroidRuntim.cpp文件中,就会查到相关的jni调用的函数指向,处理完这些,就会进入java层的zygote流程

小结

从上面的流程可以看出,在Zygote进程中通过startVm方法启动了虚拟机,后续应用进程通过zygote孵化拷贝fork出新的进程,就会复制zygote中的虚拟机,所以每个应用进程会有自己独立的虚拟机,虚拟机的主要功能就是实现进程的内存管理(堆区,方法区,栈之类的),每个进程独立管理自己的内存,遇到各种内存问题导致进程崩溃而相互之间不会影响,做到了进程间的隔离

Java层Zygote流程

上面的流程还是在c++代码中,通过反射执行到了ZygoteInit.main(),进入了Java层的逻辑

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

        ZygoteHooks.startZygoteNoThreadCreation(); //调用native函数,确保当前没有其他线程在运行,主要出于安全的考虑

        Runnable caller;
        try {
            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            //解析参数,得到上述变量的值
            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);     //默认情况,预加载信息
                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 进程进入无限循环,处理请求
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

    }

通过上述源码,zygote的Java层启动流程梳理一下

  • preload(bootTimingsTraceLog) 预加载资源,加快后续进程的启动,应用进程也是从zygote进程孵化来的,一些系统的默认资源在zygote进行预加载,加快后续进程孵化启动的速度
  • zygoteServer = new ZygoteServer(isPrimaryZygote) 实例化socket
  • Runnable r = forkSystemServer() 启动systemserver 进程,AMS
  • caller = zygoteServer.runSelectLoop(abiList) 死循环,接收AMS传过来的信息

到此Zygote进程的启动流程结束,zygote进程会去启动systemserver进程,这个进程跟各种系统服务有关系,zygote会通过socket的通信方式,接收其他进程的请求,去孵化应用进程

总结

zygote进程的启动分为native层和Java层

native层:

  • 会去初始化运行环境,创建jvm Android 虚拟机-AndroidRuntime ART
  • 注册JNI
  • 调用zygoteInit.main进入java层

java层:

  • 预加载系统资源,加快后续应用进程的启动速度
  • socket 跨进程通信方案,接收其他进程的消息
  • 循环等待消息

zygote的流程走完了,下一篇开始分析systemserver的流程了

你可能感兴趣的:(Android启动流程分析(2)-zygote进程)