1.1 Android系统架构
Android系统架构分为五层,从上到下依次是应用层、应用框架层、系统运行库层、硬件抽象层和Linux内核层,如图所示。
1.应用层(System Apps)
系统内置的应用程序以及非系统级的应用程序都属于应用层,负责与用户进行直接交互,通常都是用Java进行开发的。
2.应用框架层(Java API Framework)
应用框架层为开发人员提供了开发应用程序所需要的API,我们平常开发应用程序都是调用这一层所提供的API,当然也包括系统应用。这一层是由Java代码编写的,可以称为JavaFramework。 这一层所提供的主要组件,如表所示。
3.系统运行库层(Native) 系统运行库层分为两部分,分别是C/C++程序库和Android运行时库。
-
C/C++程序库
C/C++程序库能被Android系统中的不同组件所使用,并通过应用程序框架为开发者提供服务,下表列出了主要的C/C++程序库。
-
Android运行时库
运行时库又分为核心库和ART(Android5.0系统之后,Dalvik虚拟机被ART取代)。
核心库提供了Java语言核心库的大多数功能,这样开发者可以使用Java语言来编写Android应用。
ART 的部分主要功能包括:
-
预先 (AOT) 和即时 (JIT) 编译
-
优化的垃圾回收 (GC)
-
在 Android 9(API 级别 28)及更高版本的系统中,支持将应用软件包中的 Dalvik Executable 格式 (DEX) 文件转换为更紧凑的机器代码。
-
更好的调试支持,包括专用采样分析器、详细的诊断异常和崩溃报告,并且能够设置观察点以监控特定字段
-
在 Android 版本 5.0(API 级别 21)之前,Dalvik 是 Android Runtime。如果您的应用在 ART 上运行效果很好,那么它应该也可在 Dalvik 上运行,但反过来不一定。
-
4.硬件抽象层(HAL)
硬件抽象层是位于操作系统内核与硬件电路之间的接口层,其目的在于将硬件抽象化,为了保护硬件厂商的知识产权,它隐藏了特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可在多种平台上进行移植。从软硬件测试的角度来看,软硬件的测试工作都可分别基于硬件抽象层来完成,使得软硬件测试工作的并行进行成为可能。通俗来讲,就是将控制硬件的动作放在硬件抽象层中。
5.Linux内核层(Linux Kernel)
Android的核心系统服务基于Linux内核,在此基础上添加了部分Android专用的驱动。系统的安全性、内存管理、进程管理、网络协议栈和驱动模型等都依赖于该内核。
1.2 僵尸进程与危害
在UNIX/Linux中,父进程使用fork创建子进程,在子进程终止之后,如果父进程并不知道子进程已经终止了,这时子进程虽然已经退出了,但是在系统进程表中还为它保留了一定的信息(比如进程号、退出状态、运行时间等),这个子进程就被称作僵尸进程。系统进程表是一项有限资源,如果系统进程表被僵尸进程耗尽的话,系统就可能无法创建新的进程了。
1.3 JVM/DVM/ART
与JVM相比,Dalvik虚拟机(DVM)是专门为移动设备定制的,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik应用作为一个独立的Linux进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。
但是DVM中的应用每次运行时,字节码都需要通过即时编译器(Just In Time,JIT)转换为机器码,这会使得应用的运行效率降低。
而在ART中,系统在安装应用时会进行一次预编译(Ahead Of Time,AOT),将字节码预先编译成机器码并存储在本地,这样应用每次运行时就不需要执行编译了,运行效率也大大提高。
2. 造火箭攻略
2.1 流程简述
1.启动电源以及系统启动
当电源按下时引导芯片代码从预定义的地方(固化在ROM)开始执行。加载引导程序BootLoader到RAM,然后执行。
2.引导程序BootLoader
引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。
设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qibootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。
引导程序分两个阶段执行:
-
第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;
-
第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。
Android引导程序可以在\bootable\bootloader\legacy\usbloader找到。传统的加载器包含两个文件,需要在这里说明:
-
init.s初始化堆栈,清零BBS段,调用main.c的_main()函数;
-
main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签。
3.Linux内核启动
当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置时,它首先在系统文件中寻找init.rc文件,并启动init进程。
4.init进程启动
创建和挂载启动所需要的文件目录,初始化和启动属性服务,解析init.rc文件并启动Zygote进程。
init进程是Linux系统中用户空间的第一个进程,进程号固定为1。Kernel启动后,在用户空间启动init进程,并调用init中的main()方法执行init进程的职责。
5.Zygote进程启动
创建Java虚拟机并为Java虚拟机注册JNI方法,创建服务器端Socket,启动SystemServer进程。
注意,Zygote进程与其它进程的交互方式是Socket方式,不是Binder方式,这是出于安全性上的考虑。
Binder方式虽然高效,但是Binder的使用看起来就像是客户端直接通过所持有的引用对象调用了服务端的方法,类似于一种强引用调用。如果Zygote进程使用Binder方式,一旦被客户端的调用造成出错进而崩溃,手机系统将会重启。Zygote进程负责孵化出各个子进程,其地位非常重要,出于安全性的考虑,该场景下的Zygote进程的交互采用Socket会更合适。
6.SystemServer进程启动
启动Binder线程池和SystemServiceManager,并且启动各种系统服务。
7.Launcher启动
被SystemServer进程启动的AMS会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。
1.3 流程图示
链接:[https://juejin.cn/post/7054477677448658975
作者:复制粘贴改改改