在手机泛滥和高速发展的时代,各种飙配置,秀功能,秀亮点的阶段,大屏+大电池已成为标配,同时手机也是最重要的社交工具的时候,大家的手机已经很少关机了,分秒必争的时候,大家都不想浪费那1分钟的开机时间,希望用手滑动那个指纹解锁图案或者触摸指纹识别器,用可爱帅气的面容就能解锁手机,直接使用。很多人似乎忘记了手机还可以开机关机呢。今天就先来聊聊Android手机开机系统启动的流程。
一、Android系统启动流程概述
Android系统启动大概包括如下部分:通电加载引导程序,引导程序bootloader启动Linux kernel,随后内核启动init进程,init进程启动后,开启Zygote孵化器,进入framework层,并创建SystemServer进程,SystemServer启动后,开启各种系统服务,随后Launcher启动加载桌面,显示已安装的应用图标,启动完毕。
二、启动流程详解
1、通电加载引导程序
当电源键被按下时,引导程序会从预定的地方开始执行,启动部分硬件,加载Bootloader到RAM中。
2、引导程序Bootloader
Bootloader是Android系统启动前的一段程序,主要含有在启动阶段由处理器执行的代码。作用是将经过压缩后的内核zImage和Ram disk加载到内存中,一旦加载完成,系统的控制器就会被转移到zImage的入口点上。
大部分厂商选择了LK(Little Kernel)启动加载器,LK主要实现了如下功能:
- 基本的硬件支持
- 找到并启动内核
- 基本的UI(这里应该指的是在系统启动前,按某些组合键能进入到的一个简单的界面,与recovery模式类似?)
- 支持串口的console
- 设备可以用作USB设备(主要是fastboot协议的功劳)
- 支持闪存分区
- 支持数字签名
为了安全考虑Android设备上的Bootloader一般都会被加锁,以防止手机被root(华为已经不提供解锁码)
3、Linux Kernel启动
由于Bootloader加载的内核仍然是压缩的状态,所以需要解压后才能正式的进入到内核中,内核启动后会加载许多子系统,因此调用了initcall机制中的一个解决方案:定义了8个初始化级别,然后kernel_init线程可以依次调用。
级别 | 注释 |
0 early | 生成初始化辅助线程,比如RCU和工作队列 |
1 core | 提供给sockets之类的核心子系统使用 |
2 postcore | 提供给bdi(块设备刷写线程)和kobjects使用 |
3 arch | 与处理器体系结构相关的初始化工作 |
4 subsys | 提供给bio、sound等子系统使用 |
5 fs | 提供给文件系统使用 |
6 device | 提供给驱动和普通模块使用 |
7 late | 分配给启动的最后一个阶段初始化的工作使用(高级内存处理,oops处理函数等) |
简而言之,内核的作用就是设置缓存、加载驱动,并在最后找init.rc文件,并启动init进程。
4、init进程启动
init进程启动后会做很多工作,比较重要的工作如下:
- 创建/dev、/proc和/sys等文件目录并进行挂载(mount)
- 调用property_init()函数,在内存中开辟一片共享的内存区域,并初始化和存储系统属性
- 检测设备是否处于“充电模式”,如果处于“充电模式”就会跳过许多初始化阶段,否则会进行正常的启动过程。
- 解析Init.rc配置文件,并启动Zygote进程
系统属性提供了一个可以全局访问的配置文件设置仓库。系统属性主要包括网络设置、所有硬件设置、域名解析模块、安全模块、日志、蓝牙、电源等属性。
init.rc配置文件,包含了5中类型的语句:Action、Command、Service、Option和Import。init.rc文件主要是记录了在不同的启动阶段,会执行一些可能在系统启动中需要执行的操作。
5、Zygote进程启动
Zygote进程也称为孵化器,主要用来创建Dalvik虚拟机、ART、应用程序进程以运行系统关键服务的SystemServer进程。Zygote通过fork的形式来创建应用程序进程和SystemServer进程,同时会在DVM中创建一个实例副本。
Zygote进程的启动主要是init.rc文字中Import了Zygote启动脚本,该脚本记录了Zygote启动时究竟使用哪个启动函数和在Zygote进程重启时,哪些进程会被重启。init.zygote32.rc文件如下:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
可以得出Zygote进程的启动主要是在app_main.cpp中的main函数开始,在该main函数中会判断目前进程是否处于Zygote进程中,如果是则会调用AppRuntime的start()函数,该start()函数其实就是AndroidRuntime.cpp中的start()函数,该函数通过JNI调用了ZygoteInit.java文件中的main方法,因此Zygote就从Native层进入到了Java框架层。随后在ZygoteInit的main方法中,主要做了如下4件事情:
- 创建一个Server端的Socket
- 预加载类和资源
- 启动SystemServer进程
- 等待AMS请求创建新的应用程序进程
简而言之,Zygote进程的启动做了如下几件事情:
- 创建DVM,并为Java虚拟机注册JNI方法
- 通过JNI调用ZygoteInit的main函数进入Zygote的Java框架层
- 创建服务端Socket
- 启动SystemServer进程
6、SystemServer进程启动
ZygoteInit.java中的startSystemServer方法中启动了SystemServer进程,在该线程中创建了Binder线程池和进入了SystemServer的main方法:①创建了Binder线程池,就可以与其他线程通讯 ②进入到SystemServer方法后会启动其他服务,比如:
- 引导服务:
· ActivityManagerService:负责四大组件的启动、切换、调度等
· LightsService:管理和显示背光LED
· UserManagerService:用户模式管理
··· - 核心服务:
· BatteryService:电池相关服务
· WebViewUpdateService:webView更新服务
··· - 其他服务:
· CameraService:摄像头服务
· BluetouthService:蓝牙管理服务
· AudioService:音频相关管理服务
···
7、Launcher启动过程
系统启动的最后一步就是通过Launcher这个程序将系统中已经安装的程序显示到桌面上。Launcher会在启动过程中请求PackageManagerService返回系统中安装的应用程序的信息,并将这些信息封装成快捷图标显示在屏幕上。
Launcher的作用如下:
- 用于启动应用程序
- 用于显示和管理应用程序的图标。