【Android】系统启动流程(zygote 进程启动流程)

前言

先上图,大致了解一下 Android 设备点击电源键开机到创建出 system_server 进程的流程,
里面细化的子流程和 system_server 之后发生的事情我将会在后续的文章中详细讲:

在这里插入图片描述
图中涉及到的这些名词都是什么呢?下面来简单的说说。

Boot Rom

当电源键按下时,引导芯片就会启动,引导芯片代码会从预定义的地方开始执行(代码存在Rom),加载引导程序 BootLoader 到 RAM,换句话说,就是启动的时候,会把引导程序代码由 ROM 中移动到 RAM 中,再去执行引导程序 BootLoader

ROM可以简单理解为硬盘,断电后内部的数据是不会丢失的。

RAM可以简单理解为运行时内存,断电后内部的数据就会丢失。

BootLoader

BootLoader 是在 Android 操作系统开始运行前的一个小程序,它的主要作用是把系统 OS 拉起来并运行,BootLoader 执行后,就会启动操作系统。

idle 进程

当操作系统启动后,就会启动系统的第一个进程,即 idle 进程,它的进程号为0。

idle 进程被启动后,会在系统文件中寻找 init.rc 文件,专门用来启动 init 进程。

除了会启动 init 进程,还会启动另一个进程: kthreadd 进程 。

init 进程

init 进程的进程号为 1,它位于内核层。

它的主要工作是初始化和管理进程,内存管理,加载 Binder Driver、Display、Camera Driver等。init 进程 是首个开辟用户空间的进程,是用户空间的鼻祖

在init进程内部,会fork出我们所熟知的一个进程:zygote进程。

kthreadd 进程

kthreadd 进程,跟 init 进程一样,都位于内核层。

它主要是用来创建内核工作线程、软中断线程等内核相关的工作,我们不需要太过关注。

zygote 进程

zygote 进程又名孵化器进程,它是 java 进程的鼻祖。

zygote 进程中,它第一个 fork 出来的进程是 system_server 进程,同时,我们设备上的 App 进程都是由 zygote 进程来创建的。

system_server 进程

Android 中常用系统服务(AMS/WMS/PMS )都是由 system_server 这个进程启动的,所以它相当重要。

zygote / 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() 方法内部,会执行 SystemServermain 方法,从而启动 system_servier 进程。

接下来,继续向下查阅 ZygoteInit.main() 方法代码:

在这里插入图片描述

会发现执行乐 zygoteServer.runSelectLoop() 方法,

该方法使 zygote 进入无限循环,等待 AMS 给他发消息(告诉 zygote 创建进程)。

至此,zygote 进程和 system_server 进程的启动流程就算简单的讲完了。这里贴个图,方便大家理解:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/yang553566463/article/details/126544996