一. Loader层
Boot ROM:
上电后,BootRom会被激活,引导芯片代码开始从预定义的地方(固化在ROM)开始执行,然后加载引导程序到RAM。Boot Loader引导程序
Boot Loader是启动Android系统之前的引导程序,引导程序是OEM厂商或者运营商加锁和限制的地方,它是针对特定的主板与芯片的。OEM厂商要么使用很受欢迎的引导程序比如redboot、uboot、ARMboot等或者开发自己的引导程序,它不是Android操作系统的一部分。
Boot Loader主要作用是检查RAM,初始化硬件参数等功能。
3 Preloader:
(1)Preloader是MTK平台独有的防止芯片被Hack的一个loader,MTK平台的bootrom会先加载preloader到SRAM中,preloader会先去初始化一些HW组件,比如通信端口(USB/Uart),外部存储设备(Emmc or Nand),内存设备(DRAM Calibration)等,最后会Load LK到DRAM中并且run LK(U-boot)。
(2)LK会从外部存储设备load boot image,包括Linux kernel和Ramdisk到DRAM中.最后LK会跳到 Linux Kernel里去执行start kernel.
(3)linux kernel会先完成一些初始化动作,mount 根文件系统和启动第一个用户进程(init 进程)
二. kernel层
Android内核与linux内核启动的方式差不多。Kernel的启动流程:
1 | alps/kernel/init/main.c |
2.1 rest_init()
1 | static noinline void __ref rest_init(void) |
- rest_init中调用kernel_thread函数启动了2个内核线程,分别是:kernel_init和kthreadd
- 调用schedule函数开启了内核的调度系统,从此linux系统开始转起来了。
- rest_init最终调用cpu_idle函数结束了整个内核的启动。
也就是说linux内核最终结束了一个函数cpu_idle。这个函数里面肯定是死循环。 - 简单来说,linux内核最终的状态是:有事干的时候去执行有意义的工作(执行各个进程任务),实在没活干的时候就去死循环(实际上死循环也可以看成是一个任务)。
- 之前已经启动了内核调度系统,调度系统会负责考评系统中所有的进程,这些进程里面只有有哪个需要被运行,调度系统就会终止cpu_idle死循环进程(空闲进程)转而去执行有意义的干活的进程。这样操作系统就转起来了。
0号进程:
swapper进程(pid=0):又称为idle进程, 叫空闲进程,由系统自动创建, 运行在内核态。
系统初始化过程Kernel由无到有开创的第一个进程, 也是唯一一个没有通过fork或者kernel_thread产生的进程。
swapper进程用于初始化进程管理、内存管理,加载Display,Camera Driver,Binder Driver等相关工作。
1号进程
init进程(pid=1):由0号进程通过kernel_thread创建,在内核空间完成初始化后, 加载init程序, 并最终运行在用户空间,init进程是所有用户进程的鼻祖。
2号进程
kthreadd进程(pid=2):由0号进程通过kernel_thread创建,是Linux系统的内核进程,会创建内核工作线程kworkder,软中断线程ksoftirqd,thermal等内核守护进程。
kthreadd运行在内核空间, 负责所有内核线程的调度和管理 , kthreadd进程是所有内核进程的鼻祖。
2.2 kernel_init()
init进程会通过kernel_init创建,这个时候是在内核态,那么怎么一步步进入用户态
1 | kernel_init->init_post->run_init_process->kernel_execve |
先是
1 | static int __init kernel_init(void * unused) |
接下来是
1 | static noinline int init_post(void) |
execute_command是bootloader传递给内核的参数,一般是/init(根目录下的init程序),也就是调用文件系统的init进程。如果找不到就会继续寻找“/sbin/init”,“/etc/init”,“/bin/init”,“/bin/sh”,找到后便执行run_init_process,且不再返回。run_init_process的函数体非常简单,仅仅是对kernel_execve函数的封装,代码如下:
1 | static void run_init_process(const char *init_filename) |
kernel_execve是linux内核中创建用户进程的方法接口,其实现位于
1 | arch/arm/kernel/sys_arm.c |
那么至此,我们已经对Android Kernel如何引导以及用户空间1号进程(init进程)如何启动做了详细分析。
三.init进程
3.1 init Process
这里的native层主要说明init进程,当kernel initialize完成之后,系统会执行第一个用户进程init,我们可以说它是root进程或者所有进程的父进程。init进程相关的代码:
1 | /system/core/init/init.cpp: |
Init进程启动过程就是代码init.cpp中main函数执行过程,我们来看看它做了什么:
1 | int main(int argc, char** argv) { |
可以看到,init进程主要完成以下功能:
- 是挂载tmpfs,devpts,proc,sysfs文件系统
- 加载解析命令 Action,service
- 运行init.rc脚步,init将会解析init.rc,并且执行init.rc中的命令
- 当一些关键进程死亡,重启该进程
- 提供Android系统属性服务
3.2 文件系统简介
tmpfs
tmpfs是一种虚拟内存文件系统,因此它会将所有的文件存储在虚拟内存中,并且tmpfs下的所有内容均为临时性的内容,如果你将tmpfs文件系统卸载后,那么它下面的内存将不复存在,tmpfs是一个独立的文件系统,不是块设备,只要挂接,立即可以使用devpts
devpts文件系统为伪终端提供的一个标准接口,它的标准挂接点/dev/pts.只要pts的主复合设备/dev/ptmx被打开,就会在/dev/pts下动态创建一个新的pty设备文件proc文件系统
proc文件系统是一个非常重要的虚拟文件系统,它可以看作是内核内部数据结构的接口,通过它我们可以获得系统信息,同时也能够在运行时修改特定的内核参数sysfs文件系统
与proc文件系统类似,sysfs文件系统也是一个不占任何磁盘空间的虚拟文件系统。它通常被挂接在/sys目录下。sysfs文件系统是Linux2.6内核引入的,它把链接在系统上的设备和总线组织成为一个分级的文件,使得它们可以在用户空间存取
四.init.rc文件和语法
init.rc文件语法是以行为单位,以空格间隔的语法,以#开始代表注释行。rc文件主要包含Action,Service,Command,Option,其中对于Action和Service的名称都是唯一的,对于重复的命令视为无效
4.1 动作Action
Action:通过trigger,即以on开头的语句,决定何时执行相关service
- on early-init,在初始化早起阶段触发
- on init;在初始化阶段触发
- on late-init;在初始化晚期阶段触发
- on boot/charger;当系统启动/充电时触发,还包含其他情况
- on property=;当属性值满足条件触发
4.2 服务Servcie
服务Service,以service开头,由init进程启动,一般运行于另外一个init进程,所以启动Service前需要判断对应的可执行文件是否存在。init生成的子进程,定义在rc文件,其中每一个service,在启动时会fork方式生成子进程
4.3 命令Command
下面列举常用的命令
- class_start : 启动属于同一个class的所有服务;
- start : 启动指定的服务,若已启动则跳过;
- stop : 停止正在运行的服务
- setprop :设置属性值
- mkdir :创建指定目录
- symlink : 创建连接到的符号链接;
- write : 向文件path中写入字符串;
- exec: fork并执行,会阻塞init进程直到程序完毕;
- exprot :设定环境变量;
- loglevel :设置log级别
4.4 可选操作Option
Options是Services的可选项,与service配合使用
- disabled: 不随class自动启动,只有根据service名才启动;
- oneshot: service退出后不再重启;
- user/group: 设置执行服务的用户/用户组,默认都是root;
- class:设置所属的类名,当所属类启动/退出时,服务也启动/停止,默认为default;
- onrestart:当服务重启时执行相应命令;
- socket: 创建名为/dev/socket/的socket
- critical: 在规定时间内该service不断重启,则系统会重启并进入恢复模式
*default: 意味着disabled=false,oneshot=false,critical=false。
所有的Service里面只有servicemanager ,zygote ,surfaceflinger这3个service有onrestart关键字来触发其他service启动过程。
五.Daemon守护进程
init.rc会启动一些daemon进程,比如ueventd,adbd,servicemaager,vold,netd,debuggerd等
1 | service ueventd /sbin/ueventd |
六. ServiceMnager
ServiceManager也是守护进程,它是Android大管家,是一个很重要的服务
1 | //servicemanager可触发healthd、zygote、media、surfaceflinger、drm重启 |
service servicemanager /system/bin/servicemanager表示服务名为servicemanager,服务运行的时候会执行/system/bin/servicemanager
七.Zygote
Zygote是第一个Java进程,并且是所有java进程的父进程,在init.zygote32.rc文件中,zygote服务启动如下
1 | //zygote可触发media、netd重启 |
Zygote入口和相关类:
1 | /frameworks/base/cmds/app_process/App_main.cpp (内含AppRuntime类) |
解释下第一行参数:
- zygote:服务名
- systen/bin/app_process:zygote所对应的可执行文件,通过pid=fork()创建子进程
- 剩下的四个参数是zygote进程的启动参数,其中最后一个参数 –start-system-server是表示zygote进程启动完成后,马上将system进程启动启动
zygote启动过程调用堆栈:
1 | App_main.main() |
zygote进程的主要工作如下:
- 解析init.zygote.rc中的参数,创建AppRuntime并调用AppRuntime.start()方法
- 调用AndroidRuntime的startVM()方法创建虚拟机,再调用startReg()注册JNI函数
- 通过JNI方法调用ZygoteInit.main(),进入第一个java世界 (frameworks/base/core/java/com/android/internal/os/ZygoteInit.java:)
- registerZygoteSocket()建立通道,zygote作为通讯的服务端,用于响应客户请求
- preload()预加载通用类,drawable和color资源,openGL以及共享库webView,提高ap启动效率
- zygote完成大部分工作,接下来再通过startSystemServer(),fork得力帮手system_server进程,也是上层framework的运行载体(frameworks/base/services/java/com/android/server/SystemServer.java)
- zygote功成身退,调用runSelectLoop(),随时待命,当接受到请求创建新进程请求时立即唤醒并执行相应工作
八.system_server
上面提到Zygote启动过程会调用startSystemserver(),可知startSystemServer()函数是system_server启动流程的起点,system_server相关函数如下:
1 | /frameworks/base/core/java/android/app/ActivityThread.java |
启动流程图如下:
进入到SystemServer.main后,调用堆栈如下:
1 | SystemServer.main |
system_server最主要的工作就是启动系统服务。通过startBootstrapServices(),startCoreServices(),startOtherServices()3个方法
【注意:版本4.4.1 的代码如下】
1 | public void initAndLoop() { |
8.1 startBootstrapServices()
[SystemServer.java]启动引导服务
1 | private void startBootstrapServices() { |
8.2 startCoreServices()
[ SystemServer.java ] 启动核心服务
1 | private void startCoreServices() { |
启动服务BatteryService,UsageStatsService,WebViewUpdateService
8.3 startOtherServices()
[ SystemServer.java ] 启动其他服务
1 | private void startOtherServices() { |
其中AMS.systemReady()的大致过程如下:
1 | public final class ActivityManagerService extends ActivityManagerNative |
ActivityManagerService的systemReady方法,在该方法里会启动系统界面以及Home程序。