Android启动全景
这篇文章是 SystemServer 系列的地图,不把“启动全景”写成一张脱离源码的流程图。我们沿着 Android 17 的真实入口回答五个问题:谁启动 app_process,它如何选择 Zygote 模式,Zygote 为什么先预加载再 fork,SystemServer 在子进程中何时接管,以及父 Zygote 最后由什么事件循环继续服务后续进程创建。
读完后,应该能从一条 boot log 或 trace 反向定位到 app_main.cpp、ZygoteInit.java、ZygoteServer.java 和 SystemServer.java 的对应阶段;也应该能解释“Zygote 已启动但 SystemServer 没起来”和“SystemServer 已发布服务但 Zygote socket 不再接受连接”分别属于哪一个 owner。
1. 先看真正的入口
源码文件:frameworks/base/cmds/app_process/app_main.cpp
相关函数:main()、AppRuntime::start()
int main(int argc, char* const argv[])
{
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// 解析 VM 参数和 app_process 内部参数。
...
bool zygote = false;
bool startSystemServer = false;
bool application = false;
...
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
}
...
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else {
runtime.start("com.android.internal.os.RuntimeInit", args, false);
}
}这里的 owner 是 native app_process,不是 Java ZygoteInit。它先消费 --zygote、--start-system-server、--application 和 --nice-name,再决定调用哪个 Java 启动类。--start-system-server 只是作为参数传给 Zygote;真正的 fork 发生在后面的 ZygoteInit.forkSystemServer(),因此不能把 app_process 解析到该参数写成“已经创建了 system_server”。
启动配置来自 init 的 service 定义。源码文件:system/core/rootdir/init.zygote64_32.rc。其中 service zygote_secondary 以 /system/bin/app_process32 ... --zygote --socket-name=zygote_secondary 启动 32 位 Zygote,并声明 socket zygote_secondary 与 usap_pool_secondary。init 负责进程、socket 和重启策略;Java Zygote 负责消费这些 socket,不负责创建 init service。
2. Zygote预加载
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
相关函数:main()、preload()、gcAndFinalize()、forkSystemServer()、ZygoteServer.runSelectLoop()
public static void main(String[] argv) {
ZygoteHooks.startZygoteNoThreadCreation();
...
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
...
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
preload(bootTimingsTraceLog);
bootTimingsTraceLog.traceEnd();
}
gcAndFinalize();
Zygote.initNativeState(isPrimaryZygote);
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
caller = zygoteServer.runSelectLoop(abiList);
}这段顺序包含三个重要约束:
startZygoteNoThreadCreation()先禁止过早创建线程,保证 fork 前运行环境可控。preload()和gcAndFinalize()在父 Zygote 中完成,目的是让常用类、资源和 dex cache 进入可由子进程共享的地址空间;它们不是 SystemServer 服务初始化。forkSystemServer()的返回值区分父子进程:父 Zygote得到null,继续runSelectLoop();子进程得到 Runnable,运行 SystemServer 后直接返回,不再进入 Zygote socket 循环。
3. SystemServer参数
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
相关函数:forkSystemServer()
String[] args = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=...",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs = ZygoteArguments.getInstance(commandBuffer);
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);fork 参数同时决定身份、组、capability、进程名和目标 Java 类。uid=1000 说明子进程身份切换到 system UID;capability 则先由 Zygote 根据当前容器有效能力做交集,不能简单照抄为“system_server 永远拥有完整列表”。如果参数解析、capget 或 native fork 失败,SystemServer 尚未进入 main(),问题应回到 Zygote fork 阶段,而不是查服务注册。
4. SystemServer入口
源码文件:frameworks/base/services/java/com/android/server/SystemServer.java
相关函数:main()、构造函数、run()
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
...
Looper.prepareMainLooper();
createSystemContext();
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
startApexServices(t);
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}SystemServer 的 owner 是 fork 后的 Java 子进程。createSystemContext() 建立系统上下文;四组 start*Services() 按依赖顺序创建服务、发布 Binder 或加入 LocalServices;最后主线程进入 Looper。这里的 startOtherServices() 并不是“所有服务都在同一阶段完成”,其中还会注册 boot phase 回调、等待依赖或把工作投递到线程池。
5. 父子进程分流
父路径:forkSystemServer() 返回 null 后进入 ZygoteServer.runSelectLoop(),继续接受应用进程创建命令;Zygote socket 的 owner 仍是父 Zygote。子路径:SystemServer 的 run() 进入主 Looper,服务注册和 boot phase 由它继续推进。
失败定位可以按 owner 分三类:
app_process参数或 ABI 属性失败:查app_main.cpp与 init service 配置;- preload、capability、native fork 失败:查
ZygoteInit.java、Zygote native fork 和 zygote 日志; - SystemServer 已进入
run()但服务启动失败:查SystemServer.java的具体start*Services()、SystemServiceManager和服务自身异常。
不要把 sys.boot_completed=1 当成这条主线的唯一成功标志;它表示更晚的启动阶段,不能替代 Zygote fork、SystemServer Looper 或某个 Binder 服务实际发布状态。
6. 读源码和复现命令
下面命令只做静态导航:输入是 Android 17 checkout 中的源码路径,输出是入口、分支和阶段调用;命令不会启动设备,也不会证明运行时服务一定成功。
rg -n "int main\(|--zygote|--start-system-server|runtime.start" \
frameworks/base/cmds/app_process/app_main.cpp
rg -n "public static void main|preload\(|forkSystemServer|runSelectLoop|zygoteInit" \
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
rg -n "public static void main|void run\(|startBootstrapServices|startCoreServices|startOtherServices|startApexServices|Looper.loop" \
frameworks/base/services/java/com/android/server/SystemServer.java
rg -n "service zygote|socket zygote|start-system-server|--zygote" \
system/core/rootdir/init.zygote*.rc frameworks/base/cmds/app_process7. 下一篇阅读边界
下一篇只展开 app_process 的 main() 与 AndroidRuntime::start():参数如何分成 VM 参数、Zygote 参数和应用类参数,以及 JNI/ART 初始化如何把控制权交给 ZygoteInit.main()。本文已经给出全景,不在下一篇重复预加载、SystemServer 服务组和 Binder 注册细节。
