Android 系统启动流程
Q1:android系统的层级,由下往上
1、PowerManager - 电量管理,通过BootROM到Boot loader(相当于是一个引导程序),加载kernel驱动,然后拉起用户态的第一个进程:init进程(pid=1),ps:通过汇编语言拉起的。
2、Linux内核层:linux系统秉持这一切皆文件的原则,在内核层的,都是一些驱动,如display、camera、wifi、usb、蓝牙等等。
3、HAL硬件抽象层
主要作用是向更高级别的JavaAPI框架显示设备硬件功能,当上层api要求访问设备硬件时,将该硬件组件加载为库模块。是硬件和软件之前的抽象。
4、C、C++类库native类库,Android Runtime 。
native类库:以C、C++编写的原生库,对上连接FrameWork层,对下连接HAL层,因为Java类似的高级语言不能直接和机器对话,以及对硬件功能的进一步整合,所以中间加了一层native类库。
Android Runtime:android 运行时环境,由Zygote fork出来的进程,里面的各种操作围绕着android运行时环境进行。如创建虚拟机(其中有很多操作,见后续)、启动java层main函数、释放资源、fork出各种系统服务(核心服务和非核心服务)、启动launcher等。
5、FrameWork层
java api框架。简而言之:就是使用java语言编写的Android 系统的功能集合。
6、应用层:各种常见的手机桌面应用,如系统应用(邮箱、电话、日历、浏览器等等)以及用户自己编写的app。
Q2:android 系统的启动流程:
PowerManager 开机启动Bootloader 引导程序,加载kernel驱动,然后拉起用户态的第一个进程:init进程①,然后在init进程里,会大量的从文件中加载属性,用属性来初始化属性服务(类似于windows注册表)。然后创建解析器(createParser解析方式是逐行解析,把文件以流的形式读到内存中,因为对linux来讲,一切皆文件),之后在解析的过程中,会解析到init.rc文件,然后再通过解析init.rc,来启动Zygote进程,也可以叫做Zygote服务进程。这个就是孵化器。
接下来Zygote会fork出一个子进程,在子进程里启动app_main.cpp的main函数,在这里会启动AndroidRuntime (Android Runtime.start),这时候就来到了我们熟悉的android的世界。在ART里面,会创建android 虚拟机,注册创建线程的函数、启动java层ZygoteInit的main函数,也会释放资源,进行GC、另外还会再fork出SystemServer进程,启动一系列的系统服务,包括AMS、BatteryService等,以及其他非核心服务。这些都启动完了以后,开启Looper.loop。
最后启动Launcher,来到桌面。
Q3 init进程里面做了什么
① 挂在文件,创建目录(pis,socket selinux等等)
② 初始化内核日志
③ single-handler-init 信号量
④ 初始换和启动属性服务-类似于window的注册表
⑤ 通过LoadBootScript,创建解析器,去解析很多服务,然后在这里,会解析到解析init.rc文件, init${ro.zygote}.rc,这个rc文件可能会存在很多个,比如32位的,64位的,已经主从模式的。
第五步,具体是怎么解析的呢:LoadBootScript,createParser创建解析器,然后去解析文件:getProperty(“ro.boot.init_rc”) -> parseConfig -> ParseConfigFile(文件路径) ->parseData 把文件以流的形式加载到内存中,然后parseSelection逐行解析 ,解析完成后add到列表中。
init进程:用户态的第一个进程
Zygote进程是怎么启动的?
是通过init进程fork出来的,那么问题来了,什么是fork呢?
answer:通过一个旧的进程,创建一个新的进程。类似于复制。fork的时候,代码里会返回两次,如果返回值>0,表示代码在父进程里面执行,如果是=0.表示在子进程里面执行。fork的特点:
1、当两个进程啥事都不干的时候,可以看做是一样的。
2、写时拷贝:复制的时候只会复制当前的活动线程到新的进程中去。这里就可能会导致死锁。
3、孤儿进程:fork的宿主,也就是它老爸挂了。
4、僵尸进程:没死透,还有线程。
事情发展到现在,Zygote进程已经启动了,它的主文件是app_main.cpp,在这个main方法里,它做了一件非常重要的事情:(AndroidRuntime)runtime.start。启动了android的运行时环境 奥力给。
Zygote进程里做了哪些事(在app_main.cpp里面):
1、startAndroidRuntime
2、启动ZygoteInit.java 进入java的世界 ,这里创建了Zygote的服务端,并且通过preload 加载一系列的资源到内存中。
–> prelpadResource: 加载color/drawable 等
–> 加载openGL
–> 加载TextRes
3、调用ZygoteServer类的registerServerSocket方法创建一个Zygote的socket,用来和AMS通信。(为什么不用binder:这时候binder还没有起来。)
4、forkSystemserver,通过Zygote进程去fork SystemServer服务进程
–>createSystemCotext 创建系统上下文
–>启动引导服务:在这个时候,又有了一个主角闪亮登场,他就是:AMS,BatteyService等
–>启动其他各种五花八门的服务,如input输入服务等
–>服务都启动完以后。开启Looper.loop,使自己进入侦听状态。
5、启动launcher!!!,铁子们。
在AndroidRuntime.start方法里面,主要做了哪些事?
1、设置各种启动参数,如堆空间大小等。启动虚拟机! 启动虚拟机!! 启动虚拟机!!!
—>启动虚拟机的时候做了哪些事:
创建堆空间
Attach main 主线程
创建虚拟机对象 (是一个结构体)
创建类连接器等等
2、调用startReg()函数注册jni方法
3、注册创建线程函数
一个小小的问题,app fork的对象是Zygote进程,为什么不是init进程,也不是SystemServer进程?
A:如果从init进程fork,这时候它很多事情都还没开始做 ,app需要资源也还没有加载,这样就会比较慢,而如果是从SystemServer进程去fork,有很多服务对app来讲是不一定需要的,也会浪费资源。