基于问题学习安卓系统架构
基于问题学习安卓系统架构
文章目录
1 原理
本节要了解、弄懂安卓系统架构的原理,首先将安卓系统架构完全分析清楚,再根据下载好的Android8的源码,将源码目录中的内容与系统架构联合在一起,最后总结为什么安卓系统架构要这么设计。
1.1 什么是安卓系统架构
安卓系统架构,就是从底层硬件到高层软件的一整套技术体系,用户使用的移动端设备如果使用安卓系统搭建,那么用户就可以使用安卓平台上的应用,安卓系统架构图如下:
从顶层到底层依次是:APP --> Framework --> Native --> HAL --> Kernal,接下来对这些层进行三个层次的分析:为什么要有它、是什么、在哪里,一切要从为什么入手。
APP层
-
why
我今天早上睡过头迟到了,那么我就在想,如果有一个闹钟就好了,于是就出现了手机闹钟APP,就解决了用户每天起床需要有人按时提醒上班的需求。所以当应用设计出来后,一些页面、页面跳转、功能都需要在APP层进行实现。
-
what
就如同英文直译过来一样,是一些应用软件,比如系统自带的应用如:时钟、计算器,和用户自己安装的应用如:微信、微博。应用需要给用户提供好看的外观和满足需求的功能,是安卓系统架构中用户看得见摸得着的第一个东西,直接和用户的体验挂钩。
-
where
以apk的形式安装在用户的手机上,打开手机一看全是。
源码根目录中的packages目录对应着系统应用层,如下所示。
packages目录 描述 apps 核心应用程序 experimental 第三方应用程序 inputmethods 输入法目录 providers 内容提供者目录 screensavers 屏幕保护 services 通信服务 wallpapers 墙纸
Framework层
-
why
当产品的定位和设计出来后,安卓软件工程师就要进行开发,手机上的产品,都是软件和硬件一起协助开发完成的,那是不是每次开发产品的时候都要将硬件和软件都写好呢?当然不是,这样开发的效率太低、所需要的开发知识的门槛太高了,所以就需要有人帮助安卓应用工程师把一些与系统打交道、通用的东西都封装好,变成有描述、可以调用的API接口,达到提效率、降门槛的效果。
-
what
Framework层是一些封装好的api,主要由Java代码实现。当安卓应用工程师在编程的时候,就可以调用Framework层的api对系统层面比如电源管理、消息队列、包管理等做操作。Framework同下层打交到的方式有很多种,参考:Android Framework层和Native层通信的6种方式,同上层打交到的方式就是抽象出各种Java接口。
往上层看,在AS中开发app的时候,import的各种android.*,就是Framework层的api。
package com.leo.helloworld; import android.app.ActivityManager;// 这边都是 import android.content.Context; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; public class leo extends AppCompatActivity { public void activityManagerDemo(Context context){ ActivityManager activityManager = (ActivityManager)(context.getSystemService(android.content.Context.ACTIVITY_SERVICE )) ; return; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_leo1); } }
往下层看,Framework层提供了jni.h的文件去连接Native中的C或C++代码,达到了Java代码调用C或C++代码的效果。
下面引用网上对于 ‘Framework是什么’ 的回答:
直接翻译的意思是架构,但这样说可能不懂,下面我从两个方面来给你说吧:
一是比喻来说,假设你现在要盖楼房,framework就好比一个建筑公司,它里面有专门采集石料的,专门的租夹板的,专门的磨砂,搬砖的,运输的等等一系列的,你需要做的就是要通过这家建筑公司来盖楼,比如说你要采集石料,你通过公司采购部门,直接采集来了石料,然后通过他们进行一系列的工作,这要比你自己去河里采砂,到山上去炸石头(这些活都是不使用framework的底层嵌入式开发人员做的)要简单的多,这也是为什么farmework要高效的多,所以说,对于开发人员来说,他就像是会为开发省很多事情,但这种框架下开发的软件有一定的依赖性,所以,对于不是开发人员的用户来说,如果你的电脑上有这种框架下开发的软件,你必须有这个框架软件才可以,就好像你如果要用扩展名为EXE的应用程序,你必须先有windows系统一样
另外呢,就是通过实际案例来说明framework
如果我们要完成屏幕打印“hello world”,你如果没用框架软件,你或许会先了解底层如何实现在屏幕上显示字符,又如何启动显示器,如何控制字符位置等等,然后再考虑如何打印hello world
但是在framework下,框架下的Console类下有个静态方法Write直接实现了打印,你只需要调用这个方法,然后告诉他你要打印的信息就可以了,Console.Write(“hello world”)
不管你是不是开发人员,解释的觉得还是透彻的,不懂的话可以再追问,希望能得到最佳~
Framework层主要提供的组件如下:
名称 功能描述 Activity Manager(活动管理器) 管理各个应用程序生命周期以及通常的导航回退功能 Location Manager(位置管理器) 提供地理位置以及定位功能服务 Package Manager(包管理器) 管理所有安装在Android系统中的应用程序 Notification Manager(通知管理器) 使得应用程序可以在状态栏中显示自定义的提示信息 Resource Manager(资源管理器) 提供应用程序使用的各种非代码资源,如本地化字符串、图片、布局文件、颜色文件等 Telephony Manager(电话管理器) 管理所有的移动设备功能 Window Manager(窗口管理器) 管理所有开启的窗口程序 Content Providers(内容提供器) 使得不同应用程序之间可以共享数据 View System(视图系统) 构建应用程序的基本组件 -
where
应用框架层的主要实现代码在/frameworks/base和/frameworks/av目录下,其中/frameworks/base目录结构如下所示:
/frameworks/base目录 描述 /frameworks/base目录 描述 api 定义API cmds 重要命令:am、app_proce等 core 核心库 data 字体和声音等数据文件 docs 文档 graphics 图形图像相关 include 头文件 keystore 和数据签名证书相关 libs 库 location 地理位置相关库 media 多媒体相关库 native 本地库 nfc-extras NFC相关 obex 蓝牙传输 opengl 2D/3D 图形API packages 设置、TTS、VPN程序 sax XML解析器 services 系统服务 telephony 电话通讯管理 test-runner 测试工具相关 tests 测试相关 tools 工具 wifi wifi无线网络 参考链接:Android系统架构与系统源码目录
Native/Art
Native: C/C++
-
why
首先,安卓的应用和framework层主要使用Java语言开发,但是Java是高级语言的一种,虽然在编程时比较容易学习,但是如果要完成一些复杂运算和偏向底层的操作,Java非常难实现,而使用C/C++会很简单,所以一般会使用虚拟机:JVM等,将Java代码编译后再解释成机器语言,来驱动硬件。那么除开使用虚拟机将.class文件解释后变成机器可识别的文件,我们可以通过给Java代码加上native关键字、Java代码利用jni.h文件调用C/C++代码的方式,把复杂的Java难以实现的功能,交给C/C++代码来实现。
-
what
常见一些本地服务和一些链接库等。这一层的一个特点就是通过C和C++语言实现。
-
where
C/C++程序库并不完全在一个目录中,主要的C/C++程序库如:
名称 功能描述 OpenGL ES 3D绘图函数库 Libc 从BSD继承来的标准C系统函数库,专门为基于嵌入式Linux的设备定制 Media Framework 多媒体库,支持多种常用的音频、视频格式录制和回放。 SQLite 轻型的关系型数据库引擎 SGL 底层的2D图形渲染引擎 SSL 安全套接层,是为网络通信提供安全及数据完整性的一种安全协议 FreeType 可移植的字体引擎,它提供统一的接口来访问多种字体格式文件 要查看framework层对应的native层源码,参考:如何查找native方法所对应的底层文件
Art
-
why
在安卓系统中,APP开发和Framework层开发都是Java代码,Java代码执行在虚拟机上,如:JVM。Art也是虚拟机的一种,所以其存在的理由就是为了支持Java代码编译、解释。
-
what
Art,Android Runtime,是安卓手机上运行的虚拟机,Android4.4及以前使用的都是Dalvik虚拟机,Android5.0才开始使用Art。
为什么不使用JVM做为虚拟机?
Java VM是以基于栈的虚拟机(Stack-based),而Dalvik是基于寄存器的虚拟机(Register-based)。 显然,后者最大的好处在于可以根据硬件实现更大的优化,这更适合移动设备的特点。DVM非常适合在移动终端上使用,与PC相比,它不需要很快的CPU和大量的内存空间。
为什么要从Dalvik变为Art?
- Dalvik
Android4.4及以前使用的都是Dalvik虚拟机,我们知道Apk在打包的过程中会先将Java等源码通过javac编译成.class文件,但是我们的Dalvik虚拟机只会执行.dex文件,这个时候dx会将.class文件转换成Dalvik虚拟机执行的.dex文件。Dalvik虚拟机在启动的时候会先将.dex文件转换成快速运行的机器码,又因为65535这个问题,导致我们在应用冷启动的时候有一个合包的过程,最后导致的一个结果就是我们的app启动慢,这就是Dalvik虚拟机的JIT特性(Just In Time)。 - Art
ART虚拟机是在Android5.0才开始使用的Android虚拟机,ART虚拟机必须要兼容Dalvik虚拟机的特性,但是ART有一个很好的特性AOT(ahead of time),这个特性就是我们在安装APK的时候就将dex直接处理成可直接供ART虚拟机使用的机器码,ART虚拟机将.dex文件转换成可直接运行的.oat文件,ART虚拟机天生支持多dex,所以也不会有一个合包的过程,所以ART虚拟机会很大的提升APP冷启动速度。
简而言之,就是Dalvik是边运行边解释.dex文件,Art是启动时就预解释.dex文件为.oat文件,Dalvik启动时更快,Art运行时更快。
参考链接:
一篇文章带你了解 Android的 JIT 、AOT、Dalvik、ART ,不再傻傻分不清
JVM:.java文件->.class文件->.jar文件
DVM:.java文件->.class文件->.dex文件->.apk文件
ART:.java文件->.class文件->.dex文件->.oat文件->.apk文件
- Dalvik
-
where
- .oat文件;
- art目录。
HAL层
-
why
设想一下使用Java开发后端的情况,似乎在JVM后,就直接是操作系统,利用操作系统内提供的对机器的指令完成软件对硬件的操作,但是为啥安卓系统架构中Art之下还需要有一个硬件抽象层?下面引用一下罗老师对于HAL层的介绍:
Android的硬件抽象层,简单来说,就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。也就是说,把对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在内核空间(Kernel Space),其中,硬件抽象层运行在用户空间,而Linux内核驱动程序运行在内核空间。为什么要这样安排呢?把硬件抽象层和内核驱动整合在一起放在内核空间不可行吗?从技术实现的角度来看,是可以的,然而从商业的角度来看,把对硬件的支持逻辑都放在内核空间,可能会损害厂家的利益。我们知道,Linux内核源代码版权遵循GNU License,而Android源代码版权遵循Apache License,前者在发布产品时,必须公布源代码,而后者无须发布源代码。如果把对硬件支持的所有代码都放在Linux驱动层,那就意味着发布时要公开驱动程序的源代码,而公开源代码就意味着把硬件的相关参数和实现都公开了,在手机市场竞争激烈的今天,这对厂家来说,损害是非常大的。因此,Android才会想到把对硬件的支持分成硬件抽象层和内核驱动层,内核驱动层只提供简单的访问硬件逻辑,例如读写硬件寄存器的通道,至于从硬件中读到了什么值或者写了什么值到硬件中的逻辑,都放在硬件抽象层中去了,这样就可以把商业秘密隐藏起来了。也正是由于这个分层的原因,Android被踢出了Linux内核主线代码树中。大家想想,Android放在内核空间的驱动程序对硬件的支持是不完整的,把Linux内核移植到别的机器上去时,由于缺乏硬件抽象层的支持,硬件就完全不能用了,这也是为什么说Android是开放系统而不是开源系统的原因。
参考链接:Android硬件抽象层(HAL)概要介绍和学习计划
我的理解是,其实安卓系统架构中的HAL层和Kernal层组合起来,起到的是操作系统的作用,但是为了将关键源码不开源,所以将一些不能公布的源码放在HAL层,一些能开源的代码放在Kernal层。
-
what
硬件抽象层是位于操作系统内核与硬件电路之间的接口层,其目的在于将硬件抽象化,为了保护硬件厂商的知识产权,它隐藏了特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可在多种平台上进行移植。
在HAL层,代码也是保存在jni.h和.c类型的文件中,与Framework层调用Native层不一样的是,HAL层的代码需要遵循固定的格式、命名进行编写。
-
where
- hardware/libhardware/
- hardware/libhardware_legacy/
- hardware/xxxx/
Kernal层
-
why
如果说上面的所有层,都是决定逻辑上去驱动那个硬件,那么需要有一层只负责对硬件做操作,不是说上面的所有层没办法对硬件做操作,毕竟大家都是图灵完备的Java/C/C++代码,而是要把相同类似的事物放在一起,这样可以解耦,所以Kernal层,主要负责对硬件做操作,也叫驱动层。
为什么安卓要采用linux作为操作系统呢?
Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动(如显示,音频,照相机,蓝牙,WI-FI,电源管理等等),那么Android为什么会选择采用linux呢?原因与Linux的特性有关,内核作为一个抽象层存在硬件和软件之间,强大的内存管理和进程管理,基于权限的安全模式,支持共享库,经过认证的驱动模式,Linux本身就是开源项目等等。
-
what
Android 的核心系统服务基于Linux 内核,在此基础上添加了部分Android专用的驱动。系统的安全性、内存管理、进程管理、网络协议栈和驱动模型等都依赖于该内核。
主要驱动:增强显示驱动、键盘驱动、Flash内存驱动、照相机驱动、音频驱动、蓝牙驱动、WiFi驱动、Binder IPC驱动、Power Management(电源管理),包括硬件时钟,内存分配和共享,低内存管理,kernel调试,日志设备,android IPC机制,电源管理等。
如果要写一个驱动应该怎样写呢?Android 从上层到底层-----kernel层
-
where
主要在Driver目录下。
1、Binder IPC驱动:基于OpenBinder框架的一个驱动,用于提供 Android平台的进程间通信功能。源代码位于drivers/staging/android/binder.c。
2、电源管理(PM) :一个基于标准Linux电源管理系统的轻量级Android电源管理驱动,针对嵌入式设备做了很多优化,比如电池电量。源代码位于:kernel/power/earlysuspend.c、kernel/power/consoleearlysuspend.c、kernel/power/fbearlysuspend.c、kernel/power/wakelock.c、kernel/power/userwakelock.c
3、低内存管理器:比Linux的标准的OOM机制更加灵活,它可以根据需要杀死进程以释放需要的内存。源代码位于 drivers/staging/ android/lowmemorykiller.c。
4、匿名共享内存: 为进程间提供大块共享内存,同时为内核提供回收和管理这个内存的机制。源代码位于mm/ashmem.c。
5、 PMEM :用于向用户空间提供连续的物理内存区域,DSP和某些设备只能工作在连续的物理内存上。源代码位于drivers/misc/pmem.c。
6、 Logger :一个轻量级的日志设备,用于抓取Android系统的各种日志。源代码位于drivers/staging/android/logger.c。
7、 Alarm :提供了一个定时器,用于把设备从睡眠状态唤醒,同时它还提供了一个即使在设备睡眠时也会 运行的时钟基准。源代码位于drivers/rtc/alarm.c。
8、USB Gadget:驱动 一个基于标准 Linux USB gadget驱动框架的设备驱动,Android的USB驱动是基于gaeget框 架的。源代码位于drivers/usb/gadget/。
9、Ram Console: 为了提供调试功能,Android允许将调试日志信息写入一个被称为RAM Console的设备里,它是一个基于RAM的Buffer。源代码位于drivers/staging/android / ram_console.c。
10、timed device: 提供了对设备进行定时控制的功能,目前支持vibrator和LED设备。源代码位于drivers/staging/android /timed_output.c(timed_gpio.c)。
11、Yaffs2 :是文件系统 Android采用Yaffs2作为MTD nand flash文件系统,源代码位于fs/yaffs2/目录下。Yaffs2是一个快速稳定的应用于NAND和NOR Flash的跨平台的嵌入式设备文件系统,同其他Flash文件系统相比,Yaffs2能使用更小的内存来保存其运行状态,因此它占用内存小。Yaffs2的垃圾回收非常简单而且快速,因此能表现出更好的性能。Yaffs2在大容量的NAND Flash上的性能表现尤为突出,非常适合大容量的Flash存储。
1.2 Android8源码与系统架构的关系
从安卓8的源码目录入手,分析安卓系统架构的每一层,大概在源码中的什么位置。
源码目录结构
目录图如下:
源码目录描述
Android源码根目录 | 描述 |
---|---|
art | 全新的ART运行环境 |
bionic | 系统C库 |
bootable | 启动引导相关代码 |
build | 存放系统编译规则及generic等基础开发包配置 |
cts | Android兼容性测试套件标准 |
dalvik | dalvik虚拟机 |
developers | 开发者目录 |
development | 应用程序开发相关 |
device | 设备相关配置 |
docs | 参考文档目录 |
external | 开源模组相关文件 |
frameworks | 应用程序框架,Android系统核心部分,由Java和C++编写 |
hardware | 主要是硬件抽象层的代码 |
kernel | Linux Kernal,需要单独去下载 |
libcore | 核心库相关文件 |
libnativehelper | 动态库,实现JNI库的基础 |
packages | 应用程序包 |
pdk | Plug Development Kit 的缩写,本地开发套件 |
platform_testing | 平台测试 |
prebuilts | x86和arm架构下预编译的一些资源 |
sdk | sdk和模拟器 |
system | 底层文件系统库、应用和组件 |
toolchain | 工具链文件 |
tools | 工具文件 |
Makefile | 全局Makefile文件,用来定义编译规则 |
App层:packages
Framework层:frameworks
Native/ART层
NativeC/C++:bionic
Art:art
HAL层:hardware
Kernal层:kernel
1.3 为什么安卓系统架构要这么设计
思路:从整体架构分析,再从大到小,到每层分工来分析。
从0开始,什么都没有,我们收到需求:做一款能在手机上运行的应用,分析本质,就是软件和硬件的交互,完成一种满足用户需求的产品。那么现在开始开发了,写了很多代码,配合上硬件,能完成功能,那么这些代码里面,肯定必须得有软件能直接驱动硬件的代码,而这些代码肯定是最后被调用,又因为要和硬件打交道,C语言很合适,于是选择C语言编写,这时候把这些驱动硬件的代码拉出来放在一个文件夹里面,把这个文件夹叫做操作系统代码。由于在软件选语言的时候,觉得Java的可移植性好,所以选择用Java进行开发,接下来再看看写的代码,除去驱动硬件的代码后,发现有一些代码是用来写APP的页面、页面跳转之类的,那也把这些代码整合一下,放在一个文件夹里面,就叫业务代码吧。而Java开发,那必须得有虚拟机才能变成机器识别的代码,所以又将虚拟机的代码放在一个文件夹里,就叫虚拟机代码吧。
开发的某一天,我们忽然碰到一个很复杂的功能,Java实现起来太难了,这时候想到一个办法–使用C/C++来实现,然后用Java调用这些C/C++代码来实现功能,那也把这些C/C++代码也放在一个文件夹里,就叫调用的C/C++代码吧。
开发工作结束了,现在的项目结构是:业务代码、虚拟机代码、调用的C/C++代码、操作系统代码最后连接到硬件。
在休息两天后,又接到新的需求,要开发另外一款新的产品,这下根据上一款项目的代码,忽然发现,好像业务代码中,有一部分是可以重复使用的,比如一些位置、电话之类的通用模块,那新建一个文件夹,把这部分重复的代码也放在一个文件夹里面,就叫通用代码吧。这时候忽然收到通知,操作系统的代码要求要开源了,但是里面有一部分代码涉及商业机密不允许开源啊,于是把这部分无法开源的代码放在一个文件夹里,就叫不开源代码吧。
第二款APP开发结束了,现在的项目结构是:业务代码、通用代码、虚拟机代码、调用的C/C++代码、不开源代码、操作系统代码,对应了安卓系统架构的:APP层、Framework层、Art、Native、HAL层、Kernal层。
本文地址:https://blog.csdn.net/qq_19903753/article/details/107951546
下一篇: Android 插件化开发 代码范例
推荐阅读
-
记录修改安卓5.0系统浏览器UI遇到的部分问题
-
外媒曝华为备份操作系统实为Aurora OS:基于旗鱼OS开发、兼容安卓
-
详解Vue-cli3 项目在安卓低版本系统和IE上白屏问题解决
-
安卓系统后台进程问题分析整理
-
基于问题学习安卓系统架构
-
碎片化问题让安卓尴尬:第一大系统被Win10/iOS 11完爆
-
【安卓学习之开发工具】Android Studio安卓架构AndroidProject 编译问题
-
微软CEO:选择安卓毫不犹豫 无意重建基于Windows的移动操作系统
-
SDIO_WiFi驱动学习之安卓WLAN架构介绍及调用流程分析
-
镜像已出 安卓11 DP 2.1系统发布:修复不少崩溃问题、更稳定流畅