网上关于android启动流程的文章很多,对于我个人而言想额外补充一些知识点总结下。下面是一张网上很常见的android 启动流程图:
所以我就顺着这张流程图从上到下总结一下.
Boot Rom
Boot Rom是嵌入在ARM芯片上的,当设备按下power键上电后,设备启动加电自检后从固定的地址开始执行,随后Boot Rom加载Bootloader代码进入内存,然后执行。
BootLoader
BootLoader类似windows上的BIOS程序,嵌入式系统有很多开源的BootLoader,比如很多Android平台厂商使用的U-boot(全名An Universal boot loader)就是开源的BootLoader。
下图是Linux系统和Android系统(MTK平台)启动流程差别,左边为Linux系统,右边为Android系统(MTK平台)。
我们根据上面的对比图,可以发现Android的启动流程设计和Linux的区别。
这里先说一点,MTK平台为了防止芯片被HACK,特意加了Pre-Loader这段程序,Pre-Loader为了保护芯片包含了一些安全功能和做一些安全检查,安全检查没问题后才加载启动U-boot程序,但Pre-Loader不是所有Android平台都有的,比如展讯的一些平台就没有。
BootLoader主要工作包括配置系统Memory、加载kernel的image、传递参数给linux kernel、获取芯片信息、跳转到kernel执行。
当然BootLoader还有一些其他的工作,比如设备在关机状态下,按下开机键,此时设备执行到BootLoader层,设备有最底启动电压,BootLoader里的代码会判断当前电池电压是否满足最低启动电压,来决定是否启动设备。
还有判断进入recovery模式/充电模式/开机模式等,也是在这一层做判断。
Kernel
在这一步会加载Linux内核,内核启动时,会设置缓存、被保护存储器、计划列表,加载驱动等等。设备很多硬件功能就是在这一层开始支持使用的。当内核完成系统设置,它会启动init进程。
另外linux的watchdog进程也是这时候启动的,watchdog是为了保证系统正常运行,或者从死循环,死锁等一场状态退出的一种机制。防止系统死机卡死,但如果系统在bootloader阶段卡死,那watchdog就不起作用了。
init
init进程(/system/core/init)是Linux系统第一个在用户空间创建的进程。Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间。
用户空间和内核空间使用的内存区域也是划分开的,也是为了避免用户空间的操作影响到内核空间。
init进程会启动一些关键的系统进程,比如servicemanager服务管理、zygote孵化程序、surfaceflinger、mediaserver、Property Service(我们常用的系统属性,System Properties就是由这个服务管理的)等。
init目录下有自己的语法脚本,比如init.rc、init.usb.rc、init.trace.rc等。
Zygote
Zygote负责创建JVM的环境,工作包括创建Dalvik虚拟机实例、创建system_server进程、创建socket server进程(让其他进程和zygote进程通信)、DVM预加载初始化核心的库和资源文件。
所有apk的进程都是由Zygote fork出来的,由于是linux父子进程的关系,DVM加载的core library和资源(一般是只读的)也可以被app进程使用,app进程只需要加载自己独有的资源,这样就节省下了内存。
Linux的fork()使用写时拷贝(copy-on-write)页实现。如下图所示,创建P2子进程,内核只为P2子进程创建虚拟空间,不分配物理内存,和P1父进程共享物理空间,
当P1父进程中有更改相应段的行为发生时,才为子进程分配物理空间。
所以Zygote在创建子进程前加载的资源可以直接被子进程调用,同为了避免写入资源造成重新分配问题,所以资源一般都是只读的。
Android上层的所有程序都是运行在Dalvik VM上的(ART未引入前)。DVM只执行.dex的Dalvik executable文件。每一个Android应用程序在底层都对应有一个独立的DVM实例并在其解释下执行,Java编译器编译的.class文件经过DX工具转换为.dex文件,.dex文件由类加载器处理,接着解释器根据指令集对Dalvik字节码进行解释、执行,最后交与Linux处理。
DVM通过即时编译器(JIT,just in time)将字节码转换为机器码,机器码加载到内存后执行。JIT就是在运行时(runtime)执行生成机器码并执行(比如在c语言实现的话,就是mmap一段内存,把机器码数据拷贝到这段内存里,然后用函数指针指向这段内存后执行)。
当然Android后面引入了ART取代了DVM,而在ART中,系统在安装应用时会进行一次预编译,将字节码预先编译成机器码并存储在本地,这样应用每次运行时就不需要执行编译了,运行效率也大大提升。
System Server
System Server进程由Zygote进程fork出来,这个进程加载了其他很多关键的Service,比如PMS、WMS、AMS等,从这一层开始,各种各样的Service会进行扫描安装apk,启动Launcher,关闭开机动画,app启动运行,窗口显示管理等等的工作,这一层开始后网上的文章已经有很多了,就不重复了。
这一篇文章注重概括android启动流程和补充一些细节,比较少讲android上层的启动知识点,时间已到深夜,晚安。