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
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:
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 systemprimary 使用 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
#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
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()
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. 导航与后续
# 输入 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 连接选择。
