对zygote的理解

启动

Init进程是Linux启动之后,用户空间的第一个进程,Init进程启动之后通过解读init.rc 配置文件的方式启动了zygote。

作用

Zygote是孵化器,Zygote通过fork(复制进程)的方式创建android中几乎所有的应用程序进程和SystemServer进程。
另外在Zygote进程启动的时候会创建DVM或者ART虚拟机,因
此使用fork而建立的应用程序进程和 SystemServer 进程可以在内部得到一个DVM或者ART的实例副本,
这样就保障了每个app进程在Zygote fork的那一刻就有了虚拟机。

启动SystemServer,SystemServer需要用到Zygote准备好的一些资源:常用类,JNI函数,主题资源,共享库等,SystemServer直接从Zygote继承这些资源,对性能有很大提升。

Android的程序虽然也是使用Java/Kotlin语言编码,并生成.class字节码,但并不能直接运行在JVM(JAVA虚拟机)上,而是运行在自己的虚拟机上。而Android程序之所以不能在JVM上运行的根本原因是.class字节码文件并不是Android的最终可执行文件(执行效率问题),而是一个过渡产物,最终会生成dex文件在Android虚拟机(DVM或者ART)上执行。

Dilvik 虚拟机:Android 5.0 版本之前使用。执行程序原理:解释器逐条读入字节码0 -> 逐条翻译成机器码(Android2.2之后使用JIT即时编译技术,将解释过的机器码缓存起来,下次再执行时到这个方法的时候,则直接从缓存里面取出机器码来执行。) -> 执行机器码

ART虚拟机:Android 5.0 版本后全面使用。使用了AOT提前编译技术,Android 7.0以前,采用AOT全量预编译,Apk安装时预编译dex生成对应的机器码oat文件,造成安装时间过长。Android 7.0及之后,采用JIT/AOT混合编译模式,应用安装时不进行预编译,运行时使用JIT技术并记录热点代码到profile配置文件,手机空闲或充电状态的时候,系统扫描APP目录下的profile文件通过AOT对热点代码进行编译,下次启动时,根据profile文件来运行已编译好的机器码,应用运行期间会持续对热点代码进行记录,以方便在空闲或充电时进行AOT,以此循环。

Zygote启动脚本

init.rc文件中采用了如下所示的Import类型语句来导入Zygote启动脚本:
import /init.${ro.zygote}.rc
Android 5.0开始,Zygote有了32/64位之别,system/core/rootdir目录中存放着Zygote的启动脚本,ro.zygote属性取值有:

  • init.zygote32.rc
  • init.zygote64.rc
  • init.zygote64_32.rc

上述脚本文件中的部分代码如下:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start- system-server class main

执行 app_process64,该程序的路径是 /system/bin/app_process64 ,类名是 main,进
程名为 zygote。

Zygote进程启动流程

zygote进程的启动分为两大部分,第一部分:执行Native层面的代码,这个过程主要包含:虚拟机启
动,JNI资源函数的注册,启动zygote的java层;第二部分:执行java层面的代码,这个过程主要包含:
zygote脚本解读,加载公用的各种资源,创建socket服务器并在runSelectionLoop中死循环等待socket
消息,fork 了systemServer进程等操作。

init脚本执行的是 /frameworks/base/cmds/app_process/app_main.cpp 中的 main 方法, 在main 方法中会启动 zygote 进程:

runtime.start("com.android.internal.os.ZygoteInit", args, zygote);

runtime.start 实际执行的是 /frameworks/base/core/jni/AndroidRuntime.cpp 的 start 方法

  1. 启动java虚拟机;
  2. 注册android SDK需要使用的JNI方法;
  3. 执行ZygoteInit的main函数;
  4. 启动zygote的java层代码;
  5. 最终Zygote就从Native层进入了Java FrameWork层;
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote) { 
    // 1.启动 java 虚拟机 
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { 
          return;
     }
     onVmCreated(env); 
    // 2.为Java虚拟机注册JNI方法
    if (startReg(env) < 0) { 
        ALOGE("Unable to register all android natives\n"); 
        return; 
    }
    // 3.classNameStr是传入的参数,值为com.android.internall.os.ZygoteInit 
    classNameStr = env->NewStringUTF(className); 
    // 4.使用toSlashClassName函数将className的 "." 替换为 "/",得到 com/android/internal/os/ZygoteInit 
    char* slashClassName = toSlashClassName(className != NULL ? className : ""); 
    jclass startClass = env->FindClass(slashClassName); 
    if (startClass == NULL) { 
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); 
    } else { 
        // 5.找到 ZygoteInit 中的 main 函数 
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); 
        if (startMeth == NULL) { 
            ALOGE("JavaVM unable to find main() in '%s'\n", className); 
        } else { 
            // 6.使用JNI调用ZygoteInit的main函数 
            env->CallStaticVoidMethod(startClass, startMeth, strArray); 
      } 
    } 
}

因为zygote 启动java虚拟机和注册JNI,所以它被用来fork其他进程。
Zygote 开创了从Native层进入Java FrameWork层的先河。
在Java层执行ZygoteInit.java:

  1. 基于传参解析对应的 zygote.rc 脚本,设置进程名为zygote等信息。
  2. 创建ZygoteServer ,这个server存在的目的是让zygote接收来自socket的请求,进而fork进程,
    zygoteServer里面封装了socket。
  3. preload(bootTimingsTraceLog):加载系统资源res,加载 Android sdk class资源 和其他libc,(主要包括preloadClasses,preloadResources,preloadDrawables,preloadSharedLibraries。这些资源为后面fork 出来的App去运行而准备的。因为app 进程需要运行就需要framework 层的系统资源)。
  4. forkSystemServer,就是fork 产生了SystemServer进程。
  5. 调用 runSelectionLoop() ,接收其他进程发送的socket消息,进而创建子进程。
    main函数如下:
public static void main(String argv[]) {
        // 用来管理和子进程通信的socket服务端
        ZygoteServer zygoteServer = new ZygoteServer();

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        // 这里其实只是设置一个标志位,为 创建Java线程时做判断处理,如果是zygote进程,则不需要开启线程
        ZygoteHooks.startZygoteNoThreadCreation();

        // Zygote goes into its own process group.
        try {
            // 为zygote进程设置pgid(Process Group ID),详见: `https://stackoverflow.com/questions/41498383/what-do-the-identifiers-pid-ppid- sid-pgid-uid-euid-mean`
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        final Runnable caller;
        try {
            // Report Zygote start time to tron unless it is a runtime restart
            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
                // 获取 系统属性,判断系统重启完成
                MetricsLogger.histogram(null, "boot_zygote_init",
                        (int) SystemClock.elapsedRealtime());
            }
            // 判断当前进程是64位程序还是32位程序,并设置标记
            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
                    Trace.TRACE_TAG_DALVIK);
            bootTimingsTraceLog.traceBegin("ZygoteInit");
            // 注册到ddms服务端,内部调用 `DdmServer.registerHandler()
            RuntimeInit.enableDdms();

            boolean startSystemServer = false;
            String socketName = "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)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            zygoteServer.registerServerSocketFromEnv(socketName);
            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                    SystemClock.uptimeMillis());
                preload(bootTimingsTraceLog); // 加载各种系统res资源,类资源
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize(); //调用ZygoteHooks.gcAndFinalize()进行垃圾回收
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            bootTimingsTraceLog.traceEnd(); // ZygoteInit
            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false, 0);

            Zygote.nativeSecurityInit();

            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();

            // 结束zygote创建,其实内部是调 用`runtime`给`zygote_no_threads_`赋值为false,为创建本地线程做准备
            ZygoteHooks.stopZygoteNoThreadCreation(); 

            if (startSystemServer) {  // 判断是否需要startSystemServer
                // 通过fork的方式开启zygote的子进程,systemServer,并返回一个Runnale对象 
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer); // fork出system server

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                // 如果是zygote进程,则r==null,如果不是zygote进程,也 就是systemServer进程,则执行下面的代码
                if (r != null) {
                    r.run();
                    return;
                }
            }

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

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            // zygote进程进入死循环 中,来获取子进程发送的消息
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            // 如果发生异常,则说明zygote初始化 失败,zygoteServer也需要关闭
            zygoteServer.closeServerSocket();
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

你可能感兴趣的:(对zygote的理解)