根据上面的系统启动流程概述中的步骤,结合源码来大概过一下流程,加深印象。
从第一个用户态进程 init 被拉起后的初始化操作开始跟踪 (在线看源码,下面的截图均来自于此),进入 init.cpp 的 main 方法



上面说到 init 进程会启动 zygote 进程等等,这个 LoadBootScripts 方法就是重点,进入 LoadBootScripts 方法:

这里会加载 init.rc ,下图这个文件:

打开查看一下,是一个 Android 初始化语言(Android Init Language)编写的脚本:

回过头看一下同目录下的 zygote 文件:

回过头到 init.rc 中看一下 zygote 触发的时机:

zygote 是在 late-init 触发器中启动的。看到这里后,再回过头继续看 LoadBootScripts 是如何解析 init.rc 的,回到 init.cpp 的 LoadBootScripts 方法:

点进去看一下 ParseConfig 的源码:

这里就是一个找文件的方法,最终会走到 ParseConfigFile 方法:

再点击去看一下 ParseData 方法:

end_selection 又调用了 EndSection() :

以 Zygote 为例,Zygote 是一个 service 那么创建的解析器也就是 service.cpp,进入 service.cpp 查看 EndSection 方法:

可以看出解析出来的服务放进了一个容器中。

到这里为止,以及看到了 Zygote 是如何启动的,但是 init 进程中其他服务的启动还是没有看到。看一下 LoadBootScripts 上面的代码:


它有一个 cpp 文件:

在这里做了映射,前面 init.rc 文件中的 class_start 都会调用到映射中的 do_class_start 方法:

跟踪下 StartIfNotDisabled 方法看下服务是如何启动的:

点进去 Start 方法源码(源码较多,部分截取):

fork 了一下,这个 fork 操作的是 init 进程,fork 方法会返回两次,返回值分为三种情况: 等于0 子进程成功,接下来进入子进程执行流程;大于0,也是成功创建子进程,但会继续在父进程执行代码;小于0,则创建失败。所以,截图中下面的 if (pid == 0) 整个 if 包裹的代码都是在子进程中执行,在这个 if 的最后部分:


在这里调用execv函数启动\frameworks\base\cmds\app_process\app_main.cpp 的 main 函数,看一下源码(部分截取):


根据不同的参数去启动对应的服务。
根据上一节最后的调用流程,那么如果是 Zygote 启动,那么会调用到 AndroidRuntime 的 start 方法,并且穿入 ZygoteInit 的包名(Java文件),跟踪下 start 方法:

到这里,虚拟机已经被创建出来了,下面紧接着就是注册安卓相关功能(JNI):

startReg 主要是JNI 注册,比如安卓中常用的 new Thread 开启一个线程,最终是通过 JNI 调用到了 Native 的 pthread_create 。
下面在接着看一下 ZygoteInit 的 Main 方法:


preload 中包含一系列的初始化操作:

回过头接着看 main 方法:

上一节 ZygoteInit 中 调用了 forkSystemServer 方法,那么这个方法肯定是启动 SystemServer 服务的,点进去源码:


又调用到了 handleSystemServerProcess 方法(只截取了最后部分):

又调用到了 ZygoteInit.zygoteInit 方法:

有调用到了 RuntimeInit.applicationInit 方法:

findStaticMain:


这里可以总结出,ZygoteInit Main 方法中的 forkSystemServer 方法最终返回的是 Runnable,且 run 方法实现了对 SystemServer 类 Main 方法的调用。回过头看一下 ZygoteInit Main 方法:

这里就对应上了,接着去看 SystemServer 的 main 方法:


比如 Android 的 AMS 就是在 startBootstarpServices 中启动:

其他服务还很多就不一一看了,回到 main 函数,服务都启动完成后:

执行到这里后 就该启动手机的 Launcher 程序,Launcher 本质就是一个 app,有关 AMS 启动流程在下篇博客继续分享。
回想一下 Zygote 进程 和 init 进程 SystemServer 进程 启动后的初始化操作对比,init 进程相比于 Zygote 进程会额外加载一些驱动,过多的初始化设置;SystemServer 进程相比于 Zygote 进程会启动 AMS WMS 等等等等几十个服务。另外 fork 多线程仅仅会将发起调用的线程拷贝到子进程,这个过程可能会导致死锁问题。
假设 A 进程中有 t1,t2 两个线程,且 t1 持有 t2 的锁,t2 正在发生调用时对 A 进程进行 fokr,只会把 t2 线程拷贝到子线程,t1 线程会蒸发,那么 t2 的锁在子进程就无法释放。