Android启动
Android 架构
Android 启动
Android 系统启动流程分 4 部分:
- Android 系统启动流程之 init 进程启动
- Android 系统启动流程之 Zygote 进程启动
- Android 系统启动流之 SystemServer 进程启动
- Android 系统启动流程之 Launcher 进程启动
init 进程启动
- 启动电源,加载引导程序到 RAM,开始执行
- 执行引导程序 bootloader
bootloader 是 Android 系统开始运行前的一个小程序,主要是将 OS 拉起来,它不是 AndroidOS 的一部分。
- Kernel 启动
当 Kernel 完成系统设置时,它首先在系统文件中寻找 init.rc 文件,并启动 init 进程
- init 进程启动
init 进程主要是用来初始化和启动属性服务,并启动 Zygote 进程。 init 进程是用户进程,是所有用户进程的鼻祖,pid=1。
Zygote 进程启动
Zygote 理解?
Zygote,译为受精卵,是 Android 启动过程中第一个 Java 进程的名称。
Zygote 进程作用
Zygote 进程是 init 进程启动创建的,又称孵化器,它的作用:
- fork 创建 SystemServer 进程(继承 Zygote 的资源)
- 常用类
- JNI 函数
- 主题资源
- 共享库
- 孵化应用进程
Zygote 进程在启动的时候会创建虚拟机 (Dalvik 或 ART),因此通过其 fork 而创建的应用程序或 SystemServer 进程可以在内部获取一个虚拟机实例的副本。
Zygote 进程会启动虚拟机,加载一些系统资源,这些都是 system_server 进程和应用进程所需要的,Zygote 是这两者的一个抽象。
所有应用程序在启动时共性操作?
共性操作可以放到 zygote 中去提前处理,最大的共性便是启动运行时。其中会预先加载一些 boot class,这些类使用频繁,因此在 Zygote 中提前加载好,可以极大地提升后续应用的启动速度
Zygote 进程启动流程
init.rc→init 进程→fork+execve 系统调用→Zygote
init 进程会根据 rc 文件执行一系列启动操作,其中有一项就是启动 Zygote 进程,init 会 fork 出一个子进程,然后再通过 exec 加载 /system/bin/app_process
可执行文件
- 启动运行时:其实就是 Dalvik 字节码可以被正确理解并运行的环境,它存在于进程之中。这种环境由两部分组成:一部分负责对象的创建和回收(如类加载器、垃圾回收器等),另一部分负责程序逻辑的运行(如即时编译系统、解释器等)
- fork 出 system_server 进程
然后,zygote 便会将自身挂起,等待来自于 system_server 进程启动的请求。
Zygote Native 世界
- 启动 Android 虚拟机
- 注册 Android 的 JNI 函数
- 进入到 Java 世界:创建 Android 虚拟机实例,并调用 ZygoteInit 的 main 方法 (JNI 调用)
从这里开始从 Native 进入到 Java 层,可以认为 Zygote 开创了 Java Framework。
Zygote Java 世界
- 通过 ZygoteServer socket 监听 AMS 请求 Zygote 来创建新的应用程序进程
- 通过 forkSystemServer() fork 出 SystemServer 进程
注意
- Zygote fork 要单线程
- Zygote 多线程 fork 可能会死锁,Zygote 为了避免这个问题,在 fork 的时候把其它线程都给停掉了
- Zygote 的 IPC 没有采用 Binder,而是采用的 LocalSocket
SystemServer 进程启动
SystemServer 进程作用?
SystemServer 进程是 Zygote 进程 fork 的第一个 Java 进程。
SystemServer 进程主要是用来创建系统服务的。
- 引导服务 bootstrap services:AMS,ATMS,PM,…
- 核心服务 core services:BatteryService、GPUService,…
- 其他服务 other services:WMS,IMMS,BLE,…
SystemServer 启动
- 启动各类系统服务(分级)
Launcher 的启动
Activity 的冷启动流程
见:[[AMS#点击一个 APP 到 View 呈现中间发生了什么?]]
面试题
应用是如何启动 Binder 机制的?
应用天生就支持 binder 机制,在进程创建的时候会创建 binder 线程池,
孵化应用进程为什么不交给 SystemServer 来做,而是专门设计一个 Zygote?
- SystemServer 启动了一堆系统服务,这些服务应用程序是不需要继承的
- Zygote 进程会启动虚拟机,加载各类系统资源,是非常耗时的,由其 fork 出应用程序,就可以直接共享了,效率非常高
- Zygote 进程是 SystemServer 进程和应用进程通用资源的抽取
应用启动时候需要做很多准备工作,包括启动虚拟机、加载各类系统资源,是非常耗时的。 应用进程在启动时候,内存空间除了必要的资源外,最好是干干净净的,不要继承一堆乱七八糟的东西。 所以给 SystemServer 进程和应用进程都要用到的资源抽出来单独放在一个进程里,这就是 Zygote 进程,再由 Zygote 进程分别 fork 出 SystemServer 进程和应用进程,孵化后它们就可以各干各的事了。
Zygote 的 IPC 通信机制为什么不采用 Binder?采用 Binder 会有什么问题?
- Binder 需要多线程,可能死锁 服务端的 Binder 必须运行在线程池中,而客户端在连接服务端时会导致本线程挂起,如果服务端 Binder 意外死亡,会导致客户端本线程死锁。主要是因为 fork 不允许存在多线程,而 Binder 通信就是多线程
- 繁琐 Zygote 要启用 Binder 机制,需要打开 Binder 驱动,获得一个描述符,再通过 mmap 进行内存映射,还要注册 Binder,还要创建一个 Binder 对象注册到 ServiceManager 中去,另外 AMS 要向 Zygote 发起创建应用进程请求的话,要先从 ServiceManager 查询 Zygote 的 Binder 对象代理,然后再发起 Binder 调用,来来回回非常繁琐
- 轻量级的 IPC,用普通的管道或 Socket 就可以了