Skip to content

Zygote双进程

追踪双 Zygote 的 init 配置、ABI 列表、primary/secondary socket、客户端握手与进程创建路由。

基于android-17.0.0_r1
AndroidZygoteABI源码阅读

Zygote双进程 ​

Android 的双 Zygote 不是“所有 64 位请求固定发给 zygote、所有 32 位请求固定发给 zygote_secondary”这么简单。init 决定启动哪些二进制和 socket;app_process 从不同系统属性生成 ABI 列表;ZygoteProcess 连接后向每个 Zygote 查询它实际支持的 ABI,再按 matches(abi) 选择已有连接。primary/secondary 表示启动和连接优先级,不是 ABI 名称的硬编码别名。

1. init双进程配置 ​

源码文件:system/core/rootdir/init.zygote64_32.rc、system/core/rootdir/init.zygote64.rc

text
import /system/etc/init/hw/init.zygote64.rc

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
    rlimit nofile 32768 32768

被 import 的 init.zygote64.rc 定义 primary:

text
service zygote /system/bin/app_process64 -Xzygote /system/bin \
        --zygote --start-system-server --socket-name=zygote
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system

primary 使用 app_process64 并携带 --start-system-server;secondary 使用 app_process32、独立 socket,并启用 lazy preload。只有 primary fork SystemServer。secondary 的 onrestart restart zygote 说明它异常重启时要求 primary 也重启,避免双 Zygote 状态长期不一致。

32 位配置还把 RLIMIT_NOFILE 设为 32768,注释说明 ILP32 stdio ABI 使用 short 保存 fd;这是进程 ABI 约束,不是 Zygote socket backlog。

2. ABI列表 ​

源码文件:frameworks/base/cmds/app_process/app_main.cpp

cpp
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif

char prop[PROP_VALUE_MAX];
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);
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);

编译位数决定读取 abilist64 或 abilist32,属性值再作为 --abi-list= 传给 ZygoteInit.main()。属性缺失是 fatal,Zygote 不会以空 ABI 列表继续接受创建请求。nice name 和 socket name 是不同维度:进程显示名可以是 zygote64,协议 socket 仍是 zygote。

3. ZygoteState握手 ​

源码文件:frameworks/base/core/java/android/os/ZygoteProcess.java

相关类型:ZygoteState

java
static ZygoteState connect(LocalSocketAddress zygoteSocketAddress,
        LocalSocketAddress usapSocketAddress) throws IOException {
    final LocalSocket zygoteSessionSocket = new LocalSocket();
    try {
        zygoteSessionSocket.connect(zygoteSocketAddress);
        DataInputStream input = new DataInputStream(
                zygoteSessionSocket.getInputStream());
        BufferedWriter output = new BufferedWriter(
                new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
                Zygote.SOCKET_BUFFER_SIZE);
        return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
                zygoteSessionSocket, input, output,
                getAbiList(output, input));
    } catch (IOException ex) {
        zygoteSessionSocket.close();
        throw ex;
    }
}

boolean matches(String abi) {
    return mAbiList.contains(abi);
}

连接成功后立即执行 ABI list 查询,把服务端响应保存到 mAbiList。因此路由依据来自实际握手,不是客户端看到 socket 名后自行猜测。连接或查询失败会关闭刚创建的 session socket,避免半初始化 ZygoteState 泄漏。

4. primary优先路由 ​

源码文件:frameworks/base/core/java/android/os/ZygoteProcess.java

相关函数:openZygoteSocketIfNeeded()

java
private ZygoteState openZygoteSocketIfNeeded(String abi)
        throws ZygoteStartFailedEx {
    try {
        attemptConnectionToPrimaryZygote();
        if (primaryZygoteState.matches(abi)) {
            return primaryZygoteState;
        }

        if (mZygoteSecondarySocketAddress != null) {
            attemptConnectionToSecondaryZygote();
            if (secondaryZygoteState.matches(abi)) {
                return secondaryZygoteState;
            }
        }
    } catch (IOException ioe) {
        throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
    }
    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

算法先建立/复用 primary 连接并检查 ABI;不匹配且配置了 secondary 时才连接 secondary。两边都不匹配时明确返回 unsupported ABI,而不是回退到任意 Zygote。方法受 mLock 保护,primary/secondary ZygoteState 是长连接缓存;断开后才重新连接并重新执行 hidden API 配置。

5. SystemServer同步 ​

源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

SystemServer 子进程由 primary Zygote fork。如果设备还有 secondary Zygote,子进程路径会调用 waitForSecondaryZygote(socketName),确保另一 Zygote socket 已可连接,再继续 SystemServer 初始化。这不是让 secondary fork SystemServer,而是启动依赖同步:SystemServer 后续可能发起不同 ABI 的应用进程创建请求。

6. 配置组合 ​

init 的 zygote rc 变体决定设备是 zygote64、zygote32、zygote64_32 或相反组合。Java 路由代码只依赖构造时提供的 primary/secondary socket address 和握手 ABI list,不应把某一设备配置外推为 Android 固定架构。纯 64 位设备没有 secondary 地址,32 位 ABI 请求会进入 unsupported ABI 路径。

7. 失败与恢复 ​

  • ABI 属性缺失:对应 app_process 在进入 ZygoteInit.main() 前 fatal;
  • primary socket 连接失败:openZygoteSocketIfNeeded() 抛连接错误,不直接尝试把 secondary 当作无条件替代;
  • primary 可连但 ABI 不匹配:再尝试 secondary;
  • 两边均不匹配:返回 Unsupported zygote ABI;
  • session 握手失败:关闭临时 socket,不发布半初始化 state;
  • secondary 崩溃:init 配置触发 primary 重启,以恢复组合状态。

8. 导航与后续 ​

bash
# 输入 init 配置,输出 primary/secondary 二进制、socket、重启和 rlimit。
rg -n "service zygote|app_process32|app_process64|socket zygote|onrestart|rlimit" \
  system/core/rootdir/init.zygote*.rc

# 输入 app_process,输出编译位数对应的 ABI 属性和 Java 参数。
rg -n "ABI_LIST_PROPERTY|ZYGOTE_NICE_NAME|--abi-list" \
  frameworks/base/cmds/app_process/app_main.cpp

# 输入客户端路由,输出连接握手、ABI 匹配和 fallback。
rg -n "ZygoteState.connect|getAbiList|matches|openZygoteSocketIfNeeded|attemptConnectionToSecondaryZygote" \
  frameworks/base/core/java/android/os/ZygoteProcess.java

下一篇将进入 ZygoteServer.runSelectLoop(),展开 pollfd 构造、连接 fd、USAP event fd、超时 refill 和子进程 Runnable 返回;不会重复 ABI 连接选择。