Android Framework学习三:zygote剖析
文章目录
- Zygote工作内容
- 起始点
- 初始化步骤
- 启动 ZygoteInit
- ZygoteInit.main () 函数内部操作
- Zygote如何启动SystemServer
- 参与的类和文件
- 流程步骤
- 进程创建完成后的处理
- Framework学习之系列文章
在 Android 系统中,Zygote 是一个非常关键的进程,有 “App 孵化器” 之称 ,主要有以下特点和作用:
进程地位与创建
它是 Android 系统上所有应用进程的父进程 ,由 Linux 系统用户空间的第一个进程 ——init 进程,通过 fork 的方式创建。在一些双架构系统中,可能会创建 64 位和 32 位两个 Zygote 进程 ,现代部分设备(如 Pixel 7 及后续机型 )存在 64 位 Zygote 进程 ,还有专门针对 WebView 的 WebView Zygote 。
Zygote工作内容
这是一张描述 Android 系统中 Zygote 进程启动流程的流程图
起始点
zygote 进程启动:Zygote 是 Android 系统中一个重要的进程,是所有 Java 应用程序进程的孵化器 ,它的启动是整个流程的开端。
随后进入app_main.cpp中的main()函数,这是 Zygote 进程在 C++ 层面启动的入口函数。
初始化步骤
- 初始化 AndroidRuntime:在app_main.cpp的main()函数中,首先进行AndroidRuntime的初始化。AndroidRuntime类用于管理 Android 运行时环境相关的操作。
- 设置 zygote 启动模式:通过strcmp(arg, “–zygote”)来判断并设置当前为 Zygote 启动模式。这一步确定了进程是以 Zygote 模式启动,后续的操作都基于此模式进行。
- 给 start 函数的参数 args 赋值:通过args.add(String8(“start-system-server”)) 给start函数的参数args添加一个值 ,这个值用于指示后续启动过程中需要启动系统服务器(System Server)。
启动 ZygoteInit
AndroidRuntime::start函数:
-
runtime.start () 启动 ZygoteInit:调用runtime.start()函数来启动ZygoteInit。这是 Zygote 进程启动过程中的关键步骤,它会进一步调用一系列函数来完成虚拟机和 JNI 相关的初始化。
-
startVm () 创建虚拟机:runtime.start()内部首先调用startVm()函数,用于创建 Java 虚拟机(JVM)。这是为后续运行 Java 代码做准备,是 Zygote 进程能够执行 Java 程序的基础。
-
startReg () 注册 JNI 方法:接着调用startReg()函数,用于注册 JNI(Java Native Interface)方法。JNI 允许 Java 代码和本地 C/C++ 代码进行交互,注册这些方法后,Java 层就可以调用本地方法,本地方法也可以回调 Java 方法, 比如BitMap的创建最终调用的JNI方法。
如gRegJNI保存有要注册的JNI方法:
在startReg中把gRegJNI中JNI注册:
-
使用 JNI 调用 ZygoteInit 的 main 函数,进入 java 世界:通过env->CallStaticVoidMethod()使用 JNI 调用ZygoteInit类的main函数,至此,程序流程从 C++ 层进入到 Java 层。
ZygoteInit.main () 函数内部操作
-
preload () 预加载信息:在ZygoteInit.main()函数中,首先调用preload()函数,预加载一些类、资源等信息。预加载可以提高后续应用程序启动的速度,因为一些常用的类和资源已经提前加载到内存中。
-
new ZygoteServer () 创建 zygote 的 socket 服务:创建ZygoteServer对象,该对象用于创建 Zygote 的 socket 服务。Zygote 通过这个 socket 服务来监听客户端请求,后续应用程序进程的创建请求就是通过这个 socket 来传递的。
-
r = forkSystemServer () fork 创建 systemserver 进程:通过forkSystemServer()函数使用fork系统调用创建SystemServer进程。SystemServer进程是 Android 系统中非常重要的一个进程,它负责启动和管理系统中的各种服务,如 ActivityManagerService、PackageManagerService 等。
-
r.run () 执行 systemserver 的 main 方法:在创建SystemServer进程后,调用r.run()来执行SystemServer进程的main方法,启动系统服务相关的逻辑。
-
zygoteServer.runSelectLoop():最后调用zygoteServer.runSelectLoop(),Zygote 进入循环监听状态,等待客户端(通常是应用程序启动请求)的连接,一旦有请求到来,就会通过fork机制创建新的应用程序进程。
Zygote如何启动SystemServer
这是一张展示 Android 系统中 Zygote 进程创建 SystemServer 进程相关流程的时序图
参与的类和文件
- ZygoteInit:Java 类,在 Zygote 进程启动过程中起重要作用,负责协调 Java 层相关初始化工作。
- Zygote:Java 类,与 Zygote 进程功能紧密相关,包含一些关键的进程创建等逻辑。
- com_android_internal_os_Zygote:JNI 相关的 C++ 代码,用于实现 Java 层与本地代码的交互,这里主要涉及 Zygote 相关功能的本地实现。
- AndroidRuntime.cpp:C++ 文件,主要处理 Android 运行时环境相关操作,是连接 Java 层和底层系统的重要桥梁。
- App_main.cpp:C++ 文件,是 Zygote 进程在 C++ 层面启动的入口文件,包含main函数等关键启动逻辑。
- RuntimeInit:Java 类,负责运行时初始化相关工作。
流程步骤
- 在 ZygoteInit 的 main 函数中发起创建 SystemServer 进程
ZygoteInit的main函数首先调用forkSystemServer方法,这个方法定义在Zygote类中。 - Zygote 类的 forkSystemServer 方法
Zygote类的forkSystemServer方法调用com_android_internal_os_Zygote类的nativeForkSystemServer本地方法,通过 JNI 进入到本地 C++ 代码层。 - 进入本地 C++ 代码的 ForkCommon
nativeForkSystemServer方法调用ForkCommon中的fork()函数来创建进程。fork()是操作系统提供的系统调用,用于创建一个新进程,新进程是当前进程(Zygote 进程)的副本。 - 当fork()调用成功后,会在子进程(即将成为 SystemServer 进程)和父进程(Zygote 进程)中分别返回,子进程继续后续 SystemServer 进程的初始化,父进程则继续 Zygote 进程的其他工作。
进程创建完成后的处理
- 在 Zygote 进程这边,当收到 “进程创建完” 的通知后,调用handleSystemServerProcess方法,继续后续 Zygote 相关的处理逻辑。
- 对于新创建的 SystemServer 进程,会进行一系列初始化操作:
- 首先调用nativeZygoteInit方法,这个方法在AndroidRuntime.cpp中实现,主要进行一些本地层面的初始化。
- 接着调用onZygoteInit方法,在App_main.cpp中实现,用于构建进程对应的 binder。Binder 是 Android 系统中进程间通信(IPC)的重要机制,通过构建 binder,SystemServer 进程可以与其他进程进行通信。
- 最后调用applicationInit方法,在RuntimeInit类中实现,构建一个反射调用main函数的runnable,为 SystemServer 进程后续执行其main函数逻辑做准备。
Framework学习之系列文章
Android Framework学习一:系统框架、启动过程
Android Framework学习二:Activity创建及View绘制流程
Android Framework学习三:zygote剖析
作者:帅得不敢出门