前言
Android 源码基于 8.0。
init进程是 Linux 内核启动完成后在用户空间启动的第一个进程,主要负责初始化工作、启动属性服务、解析 init.rc 文件并启动 Zygote 进程。
Zygote 进程是一个进程孵化器,负责创建虚拟机实例、应用程序进程、系统服务进程 SystemServer。他通过 fork(复制进程)的方式创建子进程,子进程能继承父进程的系统资源如常用类、注册的 JNI 函数、主题资源、共享库等。
由于 Zygote 进程启动时会创建虚拟机实例,由 Zygote fork 出的应用程序进程和 SystemServer 进程则可以在内部获取到一个虚拟机实例副本。
Zygote的启动
init 进程会解析配置文件 init.rc,来启动一些需要在开机时就启动的系统进程,如 Zygote 进程、ServiceManager 进程等。
init.rc 是由 Android 初始化语言编写的脚本配置。由于 Android 5.0 开始支持了 64bit 程序,在 init.rc 里改成了通过 ${ro.zygote} 的值来引入 Zygote 相关的配置,
//system/core/rootdir/init.rc
import /init.${ro.zygote}.rc
${ro.zygote} 的取值有 4 种,在 init.rc 的同级目录 /system/core/rootdir 下,可以看到 4 个 Zygote 相关的配置文件,表示系统所支持程序的 bit 位数:
- init.zygote32.rc,Zygote 进程的执行程序路径为 /system/bin/app_process
- init.zygote64.rc,Zygote 进程的执行程序路径为 /system/bin/app_process64
- init.zygote32_64.rc,会启动两个 Zygote 进程,有两个执行程序,32 为主模式
- init.zygote64_32.rc,会启动两个 Zygote 进程,有两个执行程序,64 为主模式
我们看到 init.zygote32.rc 文件:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
...
第一行中,service 表示 Zygote 进程以服务的形式来启动,zygote 则是进程的名字,/system/bin/app_process 是执行程序的路径,后面几项则是传给执行程序的参数,其中 --start-system-server 表示在 Zygote 进程启动后需要启动 SystemServer 进程。
然后是最后一行,Zygote 进程是使用 socket 来进行跨进程通信的,所以会创建一个名为 zygote 的 socket,660 表示访问权限 rw-rw----,表示文件拥有者和同一群组用户具有读写权限。
init 进程启动后,通过 fork 和 execve 来启动 Zygote 进程。
//system/core/init/service.cpp
bool Service::Start() {
//fork出子进程
pid = fork();
if (pid == 0) {//子进程会返回0,父进程会返回子进程的pid
//strs[0]是执行程序的路径,即execve会运行app_process
if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
}
}
}
运行执行程序 app_process 的入口函数 main。
//frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]){
if (zygote) {
//启动 Zygote,进入 ZygoteInit.main 函数
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
}
至此 Zygote 就正式启动了。
综上,init 进程读取配置文件 init.rc 后,fork 出 Zygote 进程,通过 execve 函数执行 Zygote 的执行程序 app_process,进入 ZygoteInit 类的 main 函数。
下面详细分析 app_main 和 ZygoteInit。
native 层 app_main
前边可知 app_main.cpp 的 main 函数会调用 runtime.start()。
//frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(...){
//1. 启动 java 虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
//2. 为 java 虚拟机注册 JNI 方法
if (startReg(env) < 0) {
return;
}
//根据传入的参数找到 ZygoteInit 类和他的 main 函数
//3. 通过 JNI 调用 ZygoteInit 的 main 函数
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
Java 层 ZygoteInit
来到 ZygoteInit 的 main 函数。
//ZygoteInit.java
public static void main(String argv[]) {
//是否要创建 SystemServer
boolean startSystemServer = false;
//默认的 socket 名字
String socketName = "zygote";
//是否要延迟资源的预加载
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
//在 init.rc 文件中,有 --start-system-server 参数,表示要创建 SystemServer
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
//init.rc 没有这个参数,资源的预加载不会被延迟
enableLazyPreload = true;
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
//init.rc 可以通过 --socket-name= 指定 socket 名字来覆盖默认值
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
}
}
//1. 创建服务端 socket,名字为 socketName 即 zygote
zygoteServer.registerServerSocket(socketName);
if (!enableLazyPreload) {
//2. 没有被延迟,就预加载资源
preload(bootTimingsTraceLog);
}
if (startSystemServer) {
//3. fork 并启动 SystemServer 进程
startSystemServer(abiList, socketName, zygoteServer);
}
//4. 等待 AMS 请求(AMS 会通过 socket 请求 Zygote 来创建应用程序进程)
zygoteServer.runSelectLoop(abiList);
}
总结一下 native 层的 3 个环节和 Java 层的 4 个环节:
SystemServer 启动
SystemServer 进程主要负责创建启动系统服务如 AMS、WMS 和 PMS 等。
从前边可知 SystemServer 进程由 Zygote 进程 fork 出来并启动,在 ZygoteInit 类中。
//ZygoteInit.java
private static boolean startSystemServer(...){
String args[] = {
//...
//启动的类名:
"com.android.server.SystemServer",
};
//fork 进程,由 native 层实现
pid = Zygote.forkSystemServer();
//处理 SystemServer 进程
handleSystemServerProcess(parsedArgs);
}
private static void handleSystemServerProcess(...){
ZygoteInit.zygoteInit(...);
}
public static final void zygoteInit(...){
//启动 binder 线程池
ZygoteInit.nativeZygoteInit();
//内部经过层层调用,找到 "com.android.server.SystemServer" 类和他的 main 函数,然后执行
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
这里启动了 binder 线程池,SystemServer 进程就可以用 binder 机制来跨进程通信了(Zygote 进程是用 socket 来通信的),接着进入了 SystemServer 的 main 函数。
//SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
//创建 looper
Looper.prepareMainLooper();
//加载动态库 libandroid_servers.so
System.loadLibrary("android_servers");
//创建系统上下文
createSystemContext();
//创建 SSM,用于服务的创建、启动和生命周期管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//服务根据优先级被分成 3 批来启动:
//启动引导服务,如 AMS、PMS 等
startBootstrapServices();
//启动核心服务
startCoreServices();
//启动其他服务
startOtherServices();
//开启 looper 循环
Looper.loop();
}
看下 AMS 的启动。
//SystemServer.java
private void startBootstrapServices() {
//由SSM创建启动
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
}
private void startOtherServices() {
//AMS 准备就绪
mActivityManagerService.systemReady(...);
}
总结一下,SystemServer 进程被创建后,主要做了 3 件事情:启动 binder 线程池、创建 SystemServiceManager(SSM)、用 SSM 启动各种服务。
Launcher 的启动
Launcher作为Android的桌面,用于管理应用图标和桌面组件。
前边可知SystemServer进程会启动各种服务,其中PackageManagerService启动后会将系统中的应用程序安装完成,然后由AMS来启动Launcher。
//SystemServer.java
private void startOtherServices() {
//AMS 准备就绪
mActivityManagerService.systemReady(...);
}
跟进 ActivityManagerService。
//ActivityManagerService.java
public void systemReady(...) {
//经过层层调用来到 startHomeActivityLocked
}
boolean startHomeActivityLocked(...) {
//最终会启动 Launcher 应用的 Activity
mActivityStarter.startHomeActivityLocked(...);
}
Activity 类是 Launcher.java,剩下的流程就是加载已安装的应用程序信息,然后展示,就不具体分析了。
总结
Android 系统启动的核心流程如下:
- Linux 内核启动
- init 进程启动
- init 进程 fork 出 Zygote 进程
- Zygote 进程 fork 出 SystemServer 进程
- SystemServer 进程启动各项服务(PMS、AMS 等)
- AMS 服务启动 Launcher 桌面
Zygote 进程启动好服务端 socket 后,便会等待 AMS 的 socket 请求,来创建应用程序进程。
细节补充
- Zygote 的跨进程通信没有使用 binder,而是 socket,所以应用程序进程的 binder 机制不是继承而来,而是进程创建后自己启动的。
- Zygote 跨进程通信之所以用 socket 而不是 binder,是因为 binder 通信是多线程的,而 Zygote 需要在单线程状态下 fork 子进程来避免死锁问题。
- PMS、AMS 等系统服务启动后会调用 ServiceManager.addService() 注册,然后运行在自己的工作线程。