今天说《Android体系架构》第一篇内容,关于Android系统启动的过程。
之前我们说过Android系统
的架构图(图片来自参考链接),这里再贴一下:
而我们的Android系统
启动的过程就是架构图中从下往上运行加载的过程,这里有一张关于Android系统启动过程的总结图(图片来自参考链接gityuan.com
),大家可以先看看:
接下来就根据上述两张图具体说明下Android系统
启动过程
当按下电源按钮后,引导芯片会从固化在ROM
中的预设代码开始执行,然后加载一个引导程序也就是BootLoader
到RAM
中。
ROM,Read-Only Memor,只读存储器,信息写入后就固定下来,即时切断电源,信息也不会丢失,一般是装机过程前写入的,只能读出,不能改写。
RAM,random access memory,随机存储内容,这种存储器会在断电后丢失内容,所以用于存储短时间内的程序。
所以第一步开启电源后,做的操作就是运行预设代码,加载引导程序到RAM进行短时间存储。
引导程序Bootloader
被加载后,就开始拉起系统OS
,并运行。这个过程会检查RAM
,初始化一些硬件参数等功能。
这一层主要就是启动了linux内核
。
我们都知道Android
的核心系统服务都是基于Linux内核
的,但是这个Linux内核
到底该怎么理解呢?
Linux内核
并不指的是Linux操作系统,内核只包括最基本的内存模型,进程调度,权限安全等等。操作系统值得是一个更广的概念,不光有内核,还有自己的设备驱动,应用程序框架以及一些应用程序软件等等。所以Android、Ubuntu
等都是基于Linux内核的不同的操作系统。
所以启动了linux内核
,就是启动了内核中内存模型,进程调度,安全机制,加载驱动等等,而linux内核中的功能都需要上册的虚拟机进行调用执行。
再看看上述启动过程图,可以看到内核中主要启动了两个进程:
swapper进程(pid=0)
,该进程又称为idle进程, 系统初始化过程Kernel由无到有开创的第一个进程, 用于初始化进程管理、内存管理。并且会加载屏幕硬件,相机硬件等,这一步就会涉及到待会说到的HAL层了。kthreadd进程(pid=2)
,内核进程,会创建内核中的一些线程,以及内核守护进程。这个进程是内核进程的鼻祖。硬件抽象层
,属于内核和机器硬件电路之间的接口层。刚才说过内核进程的功能需要虚拟机去调用,那么在这之前为什么会有个硬件抽象层呢?
为了保护硬件厂商的知识产权
。怎么说呢?
首先,Linux内核的版权是GPL
(使用者可以自由的执行、复制、再发行、学习、修改与强化自由软件,而且修改后的程序也具有GPL授权)。如果硬件厂商直接把硬件驱动程序写到内核中,那就无法受保护了,其他的厂商就也可以随意使用这个硬件驱动程序原始码了。所以为了保护硬件厂商的知识产权
,在内核层上又加了一层硬件抽象层,隐藏了具体的硬件接口细节,只提供接口,可以在多个硬件平台直接移植。
相当于在内核开了一个窗口
,让上层的硬件抽象层可以去访问内核的东西,主要就是控制硬件的部分代码。然后这个窗口代码依据GPL版权
协议被公开,硬件厂商可以直接把硬件驱动程序放到了上层,而无需公开程序代码。
这一层主要提供了一些标准的接口
,用于响应硬件设备的一些模块,比如WIFI模块,蓝牙模块,都提供了相应的接口。当框架的API
请求到相关的硬件设备,系统就会为硬件加载相应的模块。
在系统启动过程中,主要就是根据内核的API
去给硬件加载模块,比如启动的时候,屏幕硬件模块肯定要加载,所以内核就会调用相应的API
,唤醒硬件中的屏幕模块。
这一层主要分为两部分:
C/C++程序库
,主要包括OpenGL ES、Media Framework、SQLite等等。Android运行时库
,其中包括核心库和虚拟机。核心库就是提供Java语言的一些核心库功能。虚拟机开始是Dalvik,后面5.0被替换为ART。上面说过,首先会加载内核,内核中会创建swapper进程
,之后会启动init进程,init进程也就诞生在Native这一层了。
入口在system/core/init/init.cpp
文件中,具体代码就不细说了,init进程
中主要做了这些事:
用户守护进程
。守护进程就是运行在后台的特殊进程,它不存在控制终端,会周期性处理一些任务。比如logd进程
,就是用来进行日志的读写操作。开机动画
。Zygote进程
。终于到了我们熟悉的地方了,Zygote进程大家都或多或少了解一些了,我们所有的应用程序都是由它孵化出来的。Media Server进程
,用来启动和管理整个C++ framework,比如相机服务(camera Service)。Framework层
大家应该都了解了,全称是Java Framework
,应用框架层。主要就是提供应用程序所需要的API,我们平时开发程序都是调用的这一层的API。当然也有专门开发Framework的Android程序员,比如一些手机厂商就需要。
Zygote进程主要干了啥呢?
创建服务端Socket
,为后续创建进程通信做准备。加载虚拟机
。没错,在Zygote进程中,会去加载下层的虚拟机。fork了System Server进程
。SystemServer进程大家应该都熟悉了吧,是Zygote fork的第一个进程,负责启动和管理Java Framework层,包括ActivityManagerService,PackageManagerService,WindowManagerService、binder线程池等等。这就涉及到APP的启动流程了,后续几篇会细说下。fork了第一个应用进程——Launcher
,以及后续的一些系统应用进程,这就到了最上面一层——应用层了。应用层,大家都太熟了,我们做出的应用和系统应用都是在这一层,和用户之间交互。
这一层所有的应用都是通过Zygote进程
孵化出来的。
最后画个流程图:
从今天开始,每篇体系化文章都有个《体系知识延伸》
的模块,主要是从Android整个架构
来看,这个章节能联系到一些什么额外的知识点。等后面知识点越来越全了之后,这个模块就可以丢一些相关链接
了。
一起看看今天的系统启动过程涉及到了哪些其他知识:
在系统启动过程中,会去启动Launcher
应用,这就涉及到了app的启动流程。包括一些服务——AMS,WMS
等等,都会在APP启动流程中发挥了重要的作用,后续会依次说到。
在这个过程中,init进程
孵化了Zygote进程
,Zygote进程
孵化了SystemServer进程
、Launcher进程
,所以这个过程会有大量的IPC。
Socket
。Binder
。signal
。关于进程间通信,Binder
就必须拎出来说下了。在Android中主要有以下应用:
这部分的知识之前说过了,我后面会重新整理并发出来。
DVM
实例中,每一个DVM实例
都运行在一个独立的进程空间中共享机制
,也就是不同应用之间运行时可以共享相同的类,这样效率就提高了Dalvik
虚拟机,每次运行应用的时候都需要编译为机器码。ART
虚拟机,每次安装的时候都会进行预编译。JIT
,安装和运行各编译一部分。在C/C++程序库中,有SQLite引擎
,可以通过c来调用SQLite的函数接口完成对数据库的操作管理。
SQLite
是没有独立进程的,它是独立的、无进程的数据库(用起来它也像一个语言库),它对数据的读写操作是直达磁盘的,而且是免费的,可供商用。
这也就是为什么Android
选择它作为数据库引擎了。
NDK(Native Development Kit)是一个开发工具包,提供了很多平台库,可以让开发者使用C和C++开发功能,管理Android设备或者Activity等等。
虽然Android是运行在虚拟机上的,但是NDK开发的程序是可以直接运行在本机内核上的,也就是不需要虚拟机这一层。
一般使用NDK开发动态库,并生成so文件打包在APK中。使用NDK开发主要有以下几点好处:
同时,为了使NDK开发出来的动态库和Java本身进行交互,就要用到JNI机制了。
JNI,属于Java虚拟机一部分,是一种Java的本地接口化技术,是提供了Java可以调用c/c++的一种机制。
http://gityuan.com/android/ https://www.jianshu.com/p/0261e6cceb3e https://www.cnblogs.com/tfanalysis/p/4073756.html https://zhuanlan.zhihu.com/p/66605252 https://blog.csdn.net/itachi85/article/details/54695046 http://m.elecfans.com/article/657339.html https://www.jianshu.com/p/45cf56172d22 https://blog.csdn.net/itachi85/article/details/54783506