先上图,大致了解一下 Android 设备点击电源键开机到创建出 system_server
进程的流程,
里面细化的子流程和 system_server
之后发生的事情我将会在后续的文章中详细讲:
图中涉及到的这些名词都是什么呢?下面来简单的说说。
当电源键按下时,引导芯片就会启动,引导芯片代码会从预定义的地方开始执行(代码存在Rom),加载引导程序 BootLoader
到 RAM,换句话说,就是启动的时候,会把引导程序代码由 ROM 中移动到 RAM 中,再去执行引导程序 BootLoader
。
ROM可以简单理解为硬盘,断电后内部的数据是不会丢失的。
RAM可以简单理解为运行时内存,断电后内部的数据就会丢失。
BootLoader 是在 Android 操作系统开始运行前的一个小程序,它的主要作用是把系统 OS 拉起来并运行,BootLoader 执行后,就会启动操作系统。
当操作系统启动后,就会启动系统的第一个进程,即 idle
进程,它的进程号为0。
当 idle
进程被启动后,会在系统文件中寻找 init.rc
文件,专门用来启动 init
进程。
除了会启动 init
进程,还会启动另一个进程: kthreadd
进程 。
init 进程的进程号为 1,它位于内核层。
它的主要工作是初始化和管理进程,内存管理,加载 Binder Driver、Display、Camera Driver等。init 进程
是首个开辟用户空间的进程,是用户空间的鼻祖。
在init进程内部,会fork出我们所熟知的一个进程:zygote进程。
kthreadd 进程,跟 init 进程一样,都位于内核层。
它主要是用来创建内核工作线程、软中断线程等内核相关的工作,我们不需要太过关注。
zygote 进程又名孵化器进程,它是 java 进程的鼻祖。
在 zygote
进程中,它第一个 fork 出来的进程是 system_server
进程,同时,我们设备上的 App 进程都是由 zygote
进程来创建的。
Android 中常用系统服务(AMS/WMS/PMS )都是由 system_server
这个进程启动的,所以它相当重要。
以下源码基于 Android 11。
在 init
进程开启后,会执行 frameworks/base/cmds/app_process/app_main.cpp
文件的 main()
方法,
该 main()
方法首先会创建 AndroidRuntime
对象 (runtime),即 Android 运行时环境对象,如下所示:
继续查阅 main()
方法,
发现执行了 runtime.start("com,android.internal.os.ZygoteInit", args, zygote)
方法,可以猜测到,这里应该是启动 zygote
进程的入口,如下:
那么我们进入 runtime.start()
方法内部看看里面写什么东西:
可以看到,在runtime.start()
方法内,执行两个方法:
startVM
方法:创建虚拟机(在这里面也看出,一个进程,内部包含一个虚拟机)startReg
方法:注册 JNI 方法,注册后才可以使用 jni 方法继续查阅 runtime.start()
方法,
可以发现下面的代码开始使用 jni 方法调用 com.android.inter.os.ZygoteInit.main()
方法,如下:
自此之后,代码将会执行到 java 层的代码,进入 java 世界。
那么为什么要用 jni 方法来调用 ZygoteInit.main()
方法呢?
原因就是 jni 是 native 层和 java 层之间的桥梁,如果想要从 native 层进入 java 层,就需要用到 jni。
zygote
进程第一个 java 进程,也是 Android 中所有 java 进程的鼻祖,比如我们平时开发的 App 都是属于 java 层进程。
接下来继续进入 ZygoteInit.main()
方法,看看里面做了什么事情:
可以看到,代码里执行乐 preload()
方法,该方法是用来预加载信息的,而这些预加载信息包括了一部分 framework
的资源,以及一部分常用的 java 类。
这部分预加载的信息,在后面创建的进程都是可以直接用的。所以这里预加载的作用就是加快了应用进程的启动速度。
继续向下查阅代码:
可以看到,执行了 zygoteServer = new ZygoteServer(isPrimaryZygote)
这行代码,这行代码是用来创建 zygote 的 socket 服务的,而这个 socket
则是用来进行跨进程通信的。
有人可能就会问了,Android 不是用 Binder 进行跨进程通信的吗,为什么这里不用 Binder 呢? 事实上,代码执行到这,Binder还没开始初始化。
继续向下查阅 ZygoteInit.main()
方法代码:
可见,这里执行了 forkSystemServer(abiList, zygoteSocketName, zygoteServer)
方法,
实际上,该方法是以 fork
的形式创建 system_setver
进程,并返回一个 Runnable 对象。
得到 Runnable 对象后,执行 r.run()
方法,而在这个 r.run()
方法内部,会执行 SystemServer 的 main
方法,从而启动 system_servier
进程。
接下来,继续向下查阅 ZygoteInit.main()
方法代码:
会发现执行乐 zygoteServer.runSelectLoop()
方法,
该方法使 zygote
进入无限循环,等待 AMS
给他发消息(告诉 zygote
创建进程)。
至此,zygote 进程和 system_server 进程的启动流程就算简单的讲完了。这里贴个图,方便大家理解: