先来一个整体的图,过一下整体流程,Android系统启动过程从下往上的一个过程是由 BootLoader 引导开机,然后依次进入 -> Kernel
-> Native
-> Framework
-> App
硬件部分
按开机键电路引导过程
BIOS的启动,是由硬件完成的,Intel x86系列的cpu的硬件都设计为加电(即开机瞬间)就进入16位实模式状态运行,此时将cpu的硬件逻辑设计为强行将CS的值设置为0xFFFF,IP的值设置为0x0000,这样CS:IP就指向了0xFFFF0这个位置,而这个位置就是BIOS程序的入口地址。
Android手机会将固态存储设备ROM预先映射到类似地址上,当开机加电的时候,cpu就会从该地址执行/boot分区下的Bootloader程序,载入linux内核到RAM中。接下来就是 检查RAM,初始化各种软硬件环境,加载驱动程序,挂载根文件系统,并开始执行根文件系统的init程序
软件部分
BootLoader
当手机处于关机状态时,长按Power键开机,引导芯片开始从固化在ROM
里的预设代码开始执行,然后加载引导程序到RAM
Linux Kernel 层
Android平台的基础是Linux内核,比如ART虚拟机最终调用底层Linux内核来执行功能。Linux内核的安全机制为Android提供相应的保障,也允许设备制造商为内核开发硬件驱动程序。
-
启动Kernel的swapper进程(pid=0):该进程又称为idle进程, 系统初始化过程Kernel由无到有开创的第一个进程, 用于初始化进程管理、内存管理,加载Display,Camera Driver,Binder Driver等相关工作;
-
启动kthreadd进程(pid=2):是Linux系统的内核进程,会创建内核工作线程kworkder,软中断线程ksoftirqd,thermal等内核守护进程。
kthreadd进程是所有内核进程的鼻祖
。
HAL 硬件抽象层
硬件抽象层 (HAL) 提供标准接口,HAL包含多个库模块,其中每个模块都为特定类型的硬件组件实现一组接口,比如WIFI/蓝牙模块,当框架API请求访问设备硬件时,Android系统将为该硬件加载相应的库模块。
Android Runtime & 系统库
每个应用都在其自己的进程中运行,都有自己的虚拟机实例。ART通过执行DEX文件可在设备运行多个虚拟机,DEX文件是一种专为Android设计的字节码格式文件,经过优化,使用内存很少。ART主要功能包括:预先(AOT)和即时(JIT)编译,优化的垃圾回收(GC),以及调试相关的支持。
这里的Native系统库主要包括init孵化来的用户空间的守护进程、HAL层以及开机动画等。启动init进程(pid=1),是Linux系统的用户进程,init进程是所有用户进程的鼻祖
。
- init进程还启动
servicemanager
(binder服务管家)、bootanim
(开机动画)等重要服务 - init进程孵化出Zygote进程,通过解析 init.rc 文件。Zygote进程是Android系统的第一个Java进程(即虚拟机进程),
Zygote是所有Java进程的父进程
,Zygote进程本身是由init进程孵化而来的。 - init进程会孵化出ueventd、logd、healthd、installd、adbd、lmkd、netd 等用户守护进程;
rc文件语法
rc文件语法是以行尾单位,以空格间隔的语法,以#开始代表注释行。rc文件主要包含Action、Service、Command、Options,其中对于Action和Service的名称都是唯一的,对于重复的命名视为无效。
Action
Action: 通过触发器trigger,即以on开头的语句来决定执行相应的service的时机,具体有如下时机:
- on early-init; 在初始化早期阶段触发;
- on init; 在初始化阶段触发;
- on late-init; 在初始化晚期阶段触发;
- on boot/charger: 当系统启动/充电时触发,还包含其他情况,此处不一一列举;
- on property:
= : 当属性值满足条件时触发;
Service
服务Service,以 service开头,由init进程启动,一般运行在init的一个子进程,所以启动service前需要判断对应的可执行文件是否存在。init生成的子进程,定义在rc文件,其中每一个service在启动时会通过fork方式生成子进程。
例如: service servicemanager /system/bin/servicemanager
代表的是服务名为servicemanager,服务执行的路径为/system/bin/servicemanager。
Command
下面列举常用的命令
- class_start <service_class_name>: 启动属于同一个class的所有服务;
- start <service_name>: 启动指定的服务,若已启动则跳过;
- stop <service_name>: 停止正在运行的服务
- setprop
:设置属性值 - mkdir
:创建指定目录 - symlink
<sym_link>: 创建连接到 的<sym_link>符号链接; - write
: 向文件path中写入字符串; - exec: fork并执行,会阻塞init进程直到程序完毕;
- exprot
:设定环境变量; - loglevel
:设置log级别
Options
Options是Service的可选项,与service配合使用
- disabled: 不随class自动启动,只有根据service名才启动;
- oneshot: service退出后不再重启;
- user/group: 设置执行服务的用户/用户组,默认都是root;
- class:设置所属的类名,当所属类启动/退出时,服务也启动/停止,默认为default;
- onrestart:当服务重启时执行相应命令;
- socket: 创建名为
/dev/socket/<name>
的socket - critical: 在规定时间内该service不断重启,则系统会重启并进入恢复模式
default: 意味着disabled=false,oneshot=false,critical=false。
Framework层
- Zygote进程,是由init进程通过解析init.rc文件后fork生成的,Zygote进程主要包含:
- 加载ZygoteInit类,注册Zygote Socket服务端套接字
- 加载虚拟机
- 提前加载类preloadClasses
- 提前加载资源preloadResouces
- System Server进程,是由Zygote进程fork而来,
System Server是Zygote孵化的第一个进程
,System Server负责启动和管理整个Java framework,包含ActivityManager,WindowManager,PackageManager,PowerManager等服务。 - Media Server进程,是由init进程fork而来,负责启动和管理整个C++ framework,包含AudioFlinger,Camera Service等服务。
App 层
-
Zygote进程孵化出的第一个App进程是Launcher,这是用户看到的桌面App;
-
Zygote进程还会创建Browser,Phone,短信等App进程,每个App至少运行在一个进程上。
-
所有的App进程都是由Zygote进程fork生成的
图解:
- App发起进程:当从桌面启动应用,则发起进程便是Launcher所在进程;当从某App内启动远程进程,则发送进程便是该App所在进程。发起进程先通过binder发送消息给system_server进程;
- system_server进程:调用Process.start()方法,通过socket向zygote进程发送创建新进程的请求;
- zygote进程:在执行
ZygoteInit.main()
后便进入runSelectLoop()
循环体内,当有客户端连接时便会执行ZygoteConnection.runOnce()方法,再经过层层调用后fork出新的应用进程; - 新进程:执行handleChildProc方法,最后调用ActivityThread.main()方法
桌面如何拉起负一屏
绑定负一屏的 AssistantOverlayService,看桌面的 AssistantLauncherClient 调用 connect,看流程图:
开机流程的图
TODO
安卓系统知识层面图
详细流程参考文章:
序号 | 进程启动 | 概述 |
---|---|---|
1 | init进程 | Linux系统中用户空间的第一个进程, Init.main |
2 | zygote进程 | 所有App进程的父进程, ZygoteInit.main |
3 | system_server进程(上篇) | 系统各大服务的载体, forkSystemServer过程 |
4 | system_server进程(下篇) | 系统各大服务的载体, SystemServer.main |
5 | servicemanager进程 | binder服务的大管家, 守护进程循环运行在binder_loop |
6 | app进程 | 通过Process.start启动App进程, ActivityThread.main |
问题
BootLoader 跟 BIOS 区别
BIOS:Basic Input/Output System(基本输入输出系统),在IBM PC兼容系统上,是一种业界标准的固件接口(来自维基百科)。有点难以理解,其实BIOS是我们电脑启动时加载的第一个程序,这个程序不是由Java语言编写也不是由C语言编写,一般是汇编程序。BIOS程序固化在主板上的一块芯片上,是连接计算机硬件与操作系统的桥梁,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序。
由于Android属于嵌入式设备,并没有像pc那样的BIOS程序。取而代之的是Bootloader——系统启动加载器。它类似于BIOS,在系统加载前,用以初始化硬件设备,建立内存空间的映像图,为最终调用系统内核准备好环境。
在Android里没有硬盘,而是ROM,它类似于硬盘存放操作系统,用户程序等。ROM跟硬盘一样也会划分为不同的区域,用于放置不同的程序,在Android中主要划分为一下几个分区:
/boot:存放引导程序,包括内核和内存操作程序
/system:相当于电脑c盘,存放Android系统及系统应用
/recovery:恢复分区,可以进入该分区进行系统恢复
/data:用户数据区,包含了用户的数据:联系人、短信、设置、用户安装的程序
/cache:安卓系统缓存区,保存系统最常访问的数据和应用程序
/misc:包含一些杂项内容,如系统设置和系统功能启用禁用设置
/sdcard:用户自己的存储区,可以存放照片,音乐,视频等文件
Native与Kernel之间通信方式、Java层与Native(C/C++)层之间通信方式?
系统调用(SysCall)层、JNI(Java Native Interface)
进程的Binder线程池又是何时启动?
应用进程怎么由Zygote进程创建?
fastboot 和 recovery 模式的区别?
Android设备有3个重要分区: 启动加载程序(Boot loader)、恢复(Recovery)和 Android ROM。
Bootloader最先加载并决定要加载的下一个分区,此分区通常是Android ROM。
Recovery模式是设备用于安装Android ROM分区更新的模式, 在对手机恢复出厂设置时也会使用Recovery模式。
默认情况下进行的recovery通常具有较少的选项,这就是自定义恢复模块可用的原因。
另一方面,Fastboot是一种协议,可用于通过USB从计算机连接到设备,并向设备的分区发出更新。 例如,当我在fastboot中时,我可以通过recovery分区进行更新。
recovery 模式:
恢复模式是一个小型Linux操作系统,可以用来对手机恢复出厂设置,或者使用供应商image对设备进行更新。
所有的设备都存在Recovery, 但并非所有设备都提供Fastboot。
fastboot 模式:
手机进入fastboot 模式,就可以安装recovery image。Fastboot现在是android sdk附带的工具,你可以用它来 re-flash 设备的分区。 因为fastboot在android之前启动,即使没有安装android,你也可以在 recovery 模式分区被破坏的情况下将它用作 recovery 模式的替代方案。
参考文献:
Android 操作系统架构开篇
Android系统启动流程(基于Android 11)
https://juejin.cn/post/6969141197596000263
Android Q 开机启动流程
https://blog.csdn.net/zhang2256109/article/details/105691449
Android从按下开机键到启动发生了什么
https://blog.csdn.net/qq_29882585/article/details/109276939
fastboot 和 recovery 模式的区别