Zygote 进程简介

Zygote 是 Android 操作系统中的一种进程,可充当具有相同应用二进制接口 (ABI) 的所有系统和应用进程的根。

在现代设备(例如 Pixel 7 及更新型号)上,会有一个 64 位 Zygote 进程。此外,还有适用于主要 ABI 的 WebView Zygote,它是一种专门的 Zygote,包含运行 WebView 的进程专用的库和资源

Zygote 执行的任务如下:

  1. 当 Android OS 初始化时,init 守护程序会生成 Zygote 进程。在某些双架构系统中,会生成两个 Zygote 进程(一个 64 位,一个 32 位)。本页仅介绍单一架构系统的情况。

  2. Zygote 可以立即生成称为非专用应用进程 (USAP) 的进程,也可以等到应用需要时再生成进程。前一种选项必须通过系统属性或 Android 调试桥命令启用。如需详细了解如何将 Zygote 配置为立即生成进程,请参阅启用非专用应用进程池

    • 如果您的设备上启用了 USAP 池,则:

      1. 系统服务器使用 Unix 域套接字连接到池中的可用 USAP。系统服务器通过更改进程的 ID (PID)、cgroup 和其他信息,请求为供应用使用而预配置 USAP。
      2. 当 USAP 完成预配置后,它会使用 PID 回复系统服务器。
      3. 当某个应用占用一个 USAP 时,该 USAP 就不再属于该池。当池中的 USAP 数量达到 1 个或更少时,Zygote 会生成新的 USAP 来为池补充 USAP。
    • 如果您的 Zygote 使用延迟求值机制来生成进程,则:

      1. 系统服务器收到应用需要进程的命令。
      2. 系统服务器使用 Unix 域套接字向相应的 Zygote 发送命令。
      3. Zygote 复刻进程并更改 PID、cgroup 和其他信息。
      4. 该进程完成后,将 PID 发送回 Zygote,然后 Zygote 将其传递回系统服务器。

启用 USAP 池

如需启用 USAP 池,请执行以下操作之一:

  • /build/make/target/product/runtime_libart.mk 中将 dalvik.vm.usap_pool_enabled 系统属性设置为 true

  • 运行以下命令:

    adb shell am broadcast -a \"com.google.android.gms.phenotype.FLAG_OVERRIDE\" --es package \"com.google.android.platform.runtime_native\" --es user \"\*\" --esa flags \"usap_pool_enabled\" --esa values \"true\" --esa types \"string\" com.google.android.gms
    

此功能启用后,每个 Zygote 都会维护一个分支进程池,用于执行应用启动进程中与应用无关的部分。

排查 Zygote 问题

本部分介绍了 Zygote 相关问题的解决方案。

Zygote 崩溃

如果您的设备无法正常重新启动,并且日志或崩溃报告显示 Zygote 存在问题,有可能是因为您最近做出了导致 initd 或系统服务器崩溃的更改。修正代码应该可以解决此问题。

SELinux 拒绝或 IO 失败

Zygote 非常注重跨进程边界的文件描述符卫生情况。如果复刻时有文件描述符,但许可名单中却没有,我们会使用 dup 系统调用来执行 /dev/null,以防止意外使用缓存的文件描述符来访问新打开的文件。

如果您要做出框架更改,更改包括尝试将资源加载到 Zygote 中,但收到 SELinux 拒绝或 IO 失败错误,请采取以下办法:

  • 对于未命名的文件描述符,在调用 Restat 时将文件描述符添加到 fds_to_ignore 向量中。

  • 对于已命名的文件描述符:

    1. 修改 WORKING_DIRECTORY/frameworks/base/core/jni/fd_utils.cpp
    2. 将该路径添加到打开文件的许可名单中。