Android 系统启动过程概述

文章摘抄自 Android系统开发进阶-系统启动流程概要,稍作修改。

(图片来自:gityuan.com/android/)

Android 系统启动过程由上图从下往上的一个过程是由 Boot Loader 引导开机,然后依次进入 -> Kernel -> Native -> Framework -> App

BootLoader

板子上电后,芯片从固化在 ROM 里预设的代码(BOOT ROM)开始执行, BOOT ROM 会加载 Bootloader 到 RAM,然后把控制权交给 BootLoader。BootLoader 的作用是初始化硬件设备,加载内核文件,然后启动内核

Linux Kernel

Linux 内核负责初始化各种软硬件环境,加载驱动程序,挂载根文件系统(/)等,最重要的是,内核启动完成后,它会在根文件系统中寻找 "init" 文件,然后启动 init 进程。

init 进程

init 进程是 Linux 系统中用户空间的第一个进程,进程号为 1,我们可以说它是 root 进程或者所有进程的父进程。源码路径为: Android/system/core/init/

init 进程的主要工作如下:

  • 挂载虚拟文件系统:如 /sys、/dev、/proc
  • 启动 property 服务
  • 启动 SELinux
  • 解析执行 init.rc 文件

zygote 进程

上面提到 init 进程在解析 init.rc 时,会创建 zygote 进程,它是 Android 系统最重要的进程之一。后续 Android 中的 App 进程都是由 zygote 进程 fork 出来的。因此,zygote 是 Android 系统所有应用的父进程。zygote 进程的实际执行文件并不是 zygote,而是 /system/bin/app_process。源码路径为: Android/frameworks/base/cmds/app_process/。 它会调用 frameworks/base/core/jni/AndroidRuntime.cpp 提供的接口启动 java 层的代码 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java。至此,我们就进入到了 java 的世界。

zygote 的主要工作如下:

  • 创建 java 虚拟机 AndroidRuntime
  • 通过 AndroidRuntime 启动 ZygoteInit 进入 java 环境。

ZygoteInit 的主要工作如下:

  • 创建 socket 服务,接受 ActivityManagerService 的应用启动请求。
  • 加载 Android framework 中的 class、res(drawable、xml信息、strings)到内存。Android 通过在 zygote 创建的时候加载资源,生成信息链接,再有应用启动,fork 子进程和父进程共享信息,不需要重新加载,同时也共享 VM。
  • 启动 SystemServer。
  • 监听 socket,当有启动应用请求到达,fork 生成 App 应用进程。

zygote 进程的出现是为了能更快的启动应用。因为在 Android 中,每个应用都有对应一个虚拟机实例(AndroidRuntime)为应用分配不同的内存地址。如果 Android 系统为每一个应用启动不同的虚拟机实例,就会消耗大量的内存以及时间。因此,更好的办法应当是通过创建一个虚拟机进程,由该 VM 进程预加载以及初始化核心库类,然后,由该 VM 进程 Fork 出其他虚拟机进程,这样就能达到代码共享、低内存占用以及最小的启动时间,而这个 VM 进程就是 zygote。

SystemServer 进程

与 Zygote 进程一样,SystemServer 进程同样是 Android 系统中最重要的进程之一。它的源码路径为: Android/frameworks/base/services/java/com/android/server/SystemServer.java

SystemServer 的主要的作用是启动各种系统服务,比如 ActivityManagerService,PackageManagerService,WindowManagerService 以及硬件相关的 Service 等服务,我们平时熟知的各种系统服务其实都是在 SystemServer 进程中启动的,这些服务都运行在同一进程(即 SystemServer 进程)的不同线程中,而当我们的应用需要使用各种系统服务的时候其实也是通过与 SystemServer 进程通讯获取各种服务对象的句柄进而执行相应的操作的。在所有的服务启动完成后,会调用各服务的 service.systemReady(...) 来通知各对应的服务,系统已经就绪。

Launcher 的启动

Launcher 的启动比较复杂,而且不同版本的 Android 系统启动逻辑可能也不太一样,所以这里就不具体讨论,后续再专门讨论。但我们可以大概说明一下启动的策略。

我们知道 SystemServer 进程再启动的过程中会启动PackageManagerService,PackageManagerService启动后会将系统中的应用程序安装完成。SystemServer启动完所有的服务后,会调用各服务的 service.systemReady(...)。Launcher 的启动逻辑就在 ActivityManagerService.systemReady() 中。

BootAnimation 退出

Launcher 启动完之后,我们还看不到 Launcher,因为被 BootAnimation 的画面挡住了。BootAnimation 的退出也比较复杂,后续再详细讨论。大概是第一个应用起来之后,其 ActivityThread 线程进入空闲状态时,会通过某种机制把 BootAnimation 给退出。这里的第一个应用自然就是 Launcher了。这样就能确保在 BootAnimation 退出后,用户看到的不是黑屏,而是我们的桌面了。

总结

至此,Android系统总算是启动完成了,上面提到的这些步骤都是非常复杂的,每个步骤都可以单独花一篇或者几篇来讨论。现在我们只需要有一个整体的概念就行,其他的细节问题后续再慢慢研究。

参考资料

相关推荐
lw向北.6 分钟前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
不爱学习的啊Biao14 分钟前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
Clockwiseee42 分钟前
PHP伪协议总结
android·开发语言·php
mmsx7 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
众拾达人10 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
吃着火锅x唱着歌11 小时前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习
_Shirley12 小时前
鸿蒙设置app更新跳转华为市场
android·华为·kotlin·harmonyos·鸿蒙
hedalei14 小时前
RK3576 Android14编译OTA包提示java.lang.UnsupportedClassVersionError问题
android·android14·rk3576
锋风Fengfeng14 小时前
安卓多渠道apk配置不同签名
android
枫_feng15 小时前
AOSP开发环境配置
android·安卓