Android 系统启动之zygote进程启动

168 阅读4分钟

0 引言

  Android 系统启动过程中一个重要的环节就是 Zygote 过程的启动。Zygote 中文翻译为 "受精卵/孵化器”,顾名思义它是 Android 运行时所有应用程序的父过程。(本博客的分析过程基于android13_r16版本。)

1 脚本启动zygote过程解析

  Android 系统启动时,最先由 Linux Kernel 启动进入 init 过程,init 是一个最基础的用户程序,用于创建其他过程和配置系统环境。这其中有一个进程是加载启动脚本(Android 系统启动之启动脚本加载过程)。我们可以在init启动脚本(/system/etc/init/hw/init.rc)中解析出需要启动的最基础过程,zygote就是其中一个重要程序。

  adb shell进入安卓系统,用cat命令打开/system/etc/init/hw/init.rc文件。在on late-init片段下面找到trigger zygote-start这一行,说明这里触发了zygote-start,所以我们继续寻找on zygote-start片段。

image.png

  继续在init.rc文件中往下寻找,可以看到on zygote-start出现了,虽然这个触发器的触发还附带了一些其他条件,暂时先不管它。这些触发器下面都带有start zygote和start zygote-secondary这两条指令。意思是启动名为zygote和zygote-secondary的服务。说明我们开始要去寻找service zygote和service zygote-secondart。

image.png

  init.rc文件下面找不到,我们需要在更大的范围内寻找。使用下面指令继续在rc配置文件中寻找。

grep -rn "service zygote" --include="*.rc" .

  可以看到在当前目录下的init.zygote64_32.rc、init.zygote32.rc和init.zygote64.rc中找到了。这些文件应该和系统的位数有关系,我们关注init.zygote64_32.rc这个文件。

image.png

  在init.zygote64_32.rc这个文件中,可以看到zygote服务是这样被定义的。

image.png

  详细分析一下这个service定义:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote

  /system/bin/app_process64是 Android 的二进制可执行程序,负责启动 Zygote 进程,它是该服务需要运行的程序;-Xzygote是启动 JVM(Java 虚拟机)的特殊参数,表示以 Zygote 模式启动虚拟机。这会启用一些优化机制,例如预加载类和资源等;/system/bin表示运行时类路径的目录位置;后面的--zygote、--start-system-server和--socket-name=zygote都是后面需要用的参数,暂时先不管。

2 app_process64源码解析

  上一节我们已经知道,zygote服务启动是通过运行app_process64程序,并携带一些特有参数来完成的,所以我们需要找到app_process64的源代码(android13_r16/frameworks/base/cmds/app_process /app_main.cpp)。

  在app_main.cpp代码中首先会创建会AppRuntime,然后会解析--zygote等参数,最后根据参数的解析结果调用runtime.start("com.android.internal.os.ZygoteInit", args, zygote)函数。

image.png

image.png

image.png

  start方法是AppRuntime类中的关键函数,用于启动Android虚拟机(Java环境)并加载指定的Java类。进入start方法内部首先可以看到是对参数的解析,这里通过是否带有参数'start-system-server'来判断该zygote是主zygote还是zygote-secondary。

image.png

  接着是配置一系列的环境变量ANDROID_ROOT、ANDROID_ART_ROOT、ANDROID_I18N_ROOT和ANDROID_TZDATA_ROOT。

image.png

  继续往下走,是开启Java虚拟机和注册native函数。

image.png

  最后通过JNI查找并调用Java类的静态main方法,这里其实指的就是ZygoteInit的main方法。

image.png

3 ZygoteInit.java源码解析

  找到ZygoteInit.java(AospProject/android13_r16/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)的main函数。里面比较重要的一部分还是参数的解析,在参数解析上面一直在区分是zygote还是zygote-secondary。因此这里有必要补充一下,它们两个服务的在rc文件中的定义。

image.png

  代码中会根据是否带有"start-system-server"和"socket-name"来区分zygote和zygote-secondary。

image.png

  接着开始创建ZygoteServer类,用于管理Zygote进程中的服务。紧接着调用forkSystemServer() 来启动系统服务。该方法会返回一个Runnable实例,如果Runnable为null则说明是在Zygote父进程中,如果不为null则通过调用r.run()来启动系统服务。

zygoteServer = new ZygoteServer(isPrimaryZygote);

if (startSystemServer) {
    Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

    // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
    // child (system_server) process.
    if (r != null) {
        r.run();
        return;
    }
}

  主zygote进程还会继续往下走,通过zygoteServer.runSelectLoop(abiList)来启动一个循环,不断地监听请求并选择合适的操作。如果请求是启动新进程,它会处理并创建新的应用进程或系统服务进程。

4 总结

  到这里zygote进程的启动过程就分析完了,接下来需要分析的是通过forkSystemServer()函数fork的新进程SystemServer。这部分内容将在下一篇博客继续分析。