[TOC]
前言
Android 底层内核空间以 【Linux Kernel 】作为基石,上层用户空间由 Native系统库、虚拟机运行环境、框架层组成,通过系统调用(Syscall)连通系统的【内核空间】与【用户空间】。
对于用户空间主要采用 C++ 和 Java 代码编写,通过 JNI技术 打通用户空间的 Java层 和 Native层(C++/C),从而连通整个系统。
一、系统架构
虽然 Android 系统非常庞大且错综复杂,需要具备全面的技术栈,但整体架构设计清晰,为了能让我们在学习安卓的过程中,有一览全局,从整体上大致了解Android系统涉及的知识层面,我们先引进一张Google官方提供的经典分层架构图。
1.一张经典架构分层图
由上静态分层架构图可知:
Android系统从下往上依次分为:
- Linux 内核
- HAL (新的 Android 架构图细化特定分出一个:Hardware Abstraction Lay (HAL)层)
- 系统Native库 和 Android运行时 环境
- Java框架层
- 应用层
每个层级提供不同的服务:
* 低层级结构提供基础服务如文件系统、内存管理、I/O操作等。
* 高层级结构建立在低层级结构之上提供具体服务如UI控件、文件访问。
复制代码
2.各层更细力度的子模块、子系统分层图
其实这5层架构每一层都包含大量的子模块或子系统, 如下图:
3.各层简单介绍
-
**应用层:**应用是用java语言编写的运行在虚拟机上的程序,比如
- Email客户端
- SMS短消息程序
- 日历等。
-
**应用框架层:**这一层是编写Google发布的核心应用时所使用的API框架,开发人员同样可以使用这些框架来开发自己的应用,这样便简化了程序开发的结构设计,但是必须要遵守其框架的开发原则。
-
**系统运行库(C/C++库以及Android运行库)层:**当使用Android应用框架时,Android系统会通过一些C/C++库来支持我们使用的各个组件,使其更好的为我们服务,比如其中的SQLite(关系数据库),Webkit(Web浏览器引擎)。
-
**Linux内核层:**Android的核心系统服务给予Linux2.6内核,如
- 安全性
- 内存管理
- 进程管理
- 网络协议栈和驱动模型等都依赖于该内核,驱动模型比如
- Binder IPC(Internet Process Connection进程间通信)驱动
- android的一个特殊驱动程序,具有单独的设备节点,提供进程间通信的功能
通过Android的系统架构图,我们不仅从宏观上认识了Android系统,同时,也给我们的学习与实践指明了方向:
- 对于从事Android应用开发,平时工作应该着重研究Android的应用框架层和应用程序层;
- 对于从事Android系统开发,平时工作应该着重研究Android的系统库和Android运行时;
- 对于从事Android驱动开发,平时工作应该着重研究Android的Linux内核
当然了,作为一个努力成为一个优秀的程序员的朋友,在不断学习进步的过程中,我们也有机会跨过自己工作的技术要求,进一步到更底层去认识我们的Android 系统。
4.从应用生命周期的角度认识Android系统架构:
二、进一步了解Android系统架构各分层
Google 提供的5层架构图已经非常经典,但为了更进一步认识 了解Android 系统架构以及其内部的环环相扣的内在联系,本文将引入系统启动架构图,以分层的架构来 进一步 揭露 Android 系统的全貌:
图解:Android 系统启动过程由上图从下往上的一个过程是由 Boot Loader 引导开机,然后依次进入 -> Kernel -> Native -> Framework -> App,接来下简要说说每个过程:
1.Loader 层
- Boot ROM:当手机处于关机状态时,长按 Power 键开机,引导芯片开始从固化在 ROM 里的预设代码开始执行,然后加载引导程序到 RAM;
- Boot Loader:这是启动 Android 系统之前的引导程序,主要是检查 RAM,初始化硬件参数等功能。
2.Linux内核层
Android 底层便是 Linux内核。例如 Android Runtime (ART 即 ART 虚拟机 ) 最终调用底层 Linux 内核来处理线程和底层内存管理等底层功能。
使用 Linux 内核可让 Android 利用 Linux 内核的安全机制为 Android 提供相应的保障,也允许设备制造商为内核开发硬件驱动程序。
随着Android的完善,随着产品完善,很多时候,应用级App简单调用系统提供API已无法满足我们开发需求,那么这个时候,我们就不得不硬着头皮去深入底层,了解NDK,学习JNI等等一些高级编程技术了。
2.1什么是 NDK ?
- 【定义】:
- Native Development Kit,是Android的一种开发工具包
- 【作用】:
- 快速开发C、 C++的动态库,并自动将so和应用一起打包成 APK
- 即可通过 NDK在 Android中 使用 JNI与本地代码(如C、C++)交互
- 【优点】:
- 运行效率高、代码安全性高、跨平台
2.2什么是 JNI ?
- 【定义】:
- Java Native Interface
- 【作用】:
- 通过 JNI 能使 Java 调用 C++
进程加载流程:
- 启动 Kernel 的 swapper 进程(pid=0):
- 该进程又称为 idle 进程, 系统初始化过程 Kernel 由无到有开创的第一个进程
- 该进程用于初始化进程管理、内存管理,加载 Display、Camera Driver、Binder Driver 等相关工作;
- 启动 kthreadd 进程(pid=2):
- 该进程是 Linux 系统的内核进程,会创建内核工作线程 kworkder、软中断线程 ksoftirqd、thermal等内核守护进程。
- kthreadd 进程是所有内核进程的鼻祖。
3.硬件抽象层 (HAL)
- 硬件抽象层 (HAL) 提供标准接口,向更高级别的 Java API 框架显示设备硬件功能。
- HAL 包含多个库模块,其中每个模块都为特定类型的硬件组件实现一组接口,比如WIFI/蓝牙模块,当框架API请求访问设备硬件时,Android系统将为该硬件加载相应的库模块。
4.Android Runtime & 核心库 和 Native 系统库
Android 应用程序是用 Java 语言开发编写的,程序在 Android运行环境 中执行;
Android运行环境 分为:**核心库(Core Labraries:安卓开发核心库)**和 **Dalvik虚拟机(DaLvik Virtual Machine)**两部分
4.1Android Runtime 安卓运行环境
- Core Libraries (安卓开发核心库,即 核心库)
- Android 包含一个核心库的集合,核心库提供了Java语言API中的大多数功能,既兼容了大多数Java语言所需要调用的功能函数,同时也包含了 Android 的一些核心API。如 android.os、android.net、android.media 等等。
- Dalvik Virtual Machine (Dalvik 虚拟机 )
- 是一种基于寄存器的 java 虚拟机,Dalvik 虚拟机主要是完成对生命周期的管理、堆栈的管理、线程的管理、安全和异常的管理以及垃圾回收等重要功能。
- Android 程序不同于J2ME(Java ME 又称为J2ME,即 Java Platform,Micro Edition)程序,每个Android应用程序都有一个专有的进程,并且不是多个程序运行在一个虚拟机中,而是每个Android程序都有一个Dalivik虚拟机的实例,并在该实例中执行。
- Dalvik虚拟机是一种基于寄存器的Java虚拟机,而不是传统的基于栈的虚拟机,并进行了内存资源使用的优化,以及支持多个虚拟机的特点。需要注意的是,不同于J2me,Android程序在虚拟机中执行的并非编译后的字节码,而是通过转换工具 dx 将 Java字节码转成 dex 格式的中间码。
Android 5.0 以下的版本 运行的是Dalvik 虚拟机。
**Android 5.0+**运行的 ART 虚拟机(Android Runtime)
对于运行 Android 5.0(API 级别 21)或更高版本的设备,每个应用都在其自己的进程中运行,并且有其自己的 Android Runtime ( 即 ART 虚拟机 ) 实例。
ART 编写为通过执行 DEX 文件在低内存设备上运行多个虚拟机,DEX 文件是一种专为 Android 设计的字节码格式,经过优化,使用的内存很少。
编译工具链(例如 Jack)将 Java 源代码编译为 DEX 字节码,使其可在 Android 平台上运行。
4.1.1Dalvik 虚拟机
每一个 Android 应用程序都是 Dalvik 虚拟机中的实例,运行在他们自己的进程中
Dalvik虚拟机设计成,在一个设备可以高效地运行多个虚拟机
Dalvik虚拟机可执行文件格式是 .dex , dex 格式是专为 Dalvik 设计的一种压缩格式,适合内存和处理器速度有限的系统
大多数虚拟机 包括 JVM 都是基于栈的,而 Dalvik 虚拟机则是基于寄存器的
两种架构各有优劣,一般而言,基于栈的机器需要更多指令,而基于寄存器的机器指令更大
dx 是一套工具,可以将 Java .class 转换成 .dex 格式
一个dex文件通常会有多个.class
由于 dex 有时必须进行最佳化,会使文件大小增加1-4倍,以 ODEX 结尾
Dalvik虚拟机 依赖于Linux 内核提供基本功能,如线程和底层内存管理
Dalvik 与 JVM 的区别:
- 1)Dalvik 基于寄存器,而 JVM 基于栈。
- 2)Dalvik虚拟机运行的是其专有的文件格式Dex,而Java虚拟机运行java字节码。
- 3)Dex文件格式可以减少整体文件尺寸,提高I/O操作的类查找速度。
- 4)每个APP对应一个独立的虚拟机实例,APP的每个线程对应一个Linux线程。
- 5)有一个特殊的虚拟机进程Zygote,其是虚拟机实例的孵化器。
-
Zygote在系统启动的时候就会产生,如果系统需要一个新的虚拟机实例,它会迅速复制自身,以最快的数据提供给系统
-
对于一些只读的系统库,所有虚拟机实例都和Zygote共享一块内存区域。
-
4.1.2ART的部分主要功能
每个应用都在其自己的进程中运行,都有自己的虚拟机实例。
-
ART 通过执行DEX文件可在设备运行多个虚拟机,DEX文件是一种专为 Android 设计的字节码格式文件,经过优化,使用内存很少。
-
ART主要功能包括:
- 预先(AOT)和即时(JIT)编译
- 优化的垃圾回收(GC)
- 以及调试相关的支持。包括:
- 专用采样分析器
- 详细的诊断异常和崩溃报告
- 并且能够设置监视点以监控特定字段
注意:
在 Android 版本 5.0(API 级别 21)之前,Dalvik 是 Android Runtime。如果用户的应用在 ART 上运行效果很好,那么它应该也可在 Dalvik 上运行,但反过来不一定(向下兼容)
Android 还包含一套核心运行时库,可提供 Java API 框架使用的 Java 编程语言大部分功能,包括一些 Java 8 语言功能。
4.2Native 系统库(系统运行库,即 原生 C/C++ 库)
这层中包含了支持整个系统正常运行的基础库,由于这些库多数都由C/C++实现,因此也被一些开发人员成为“C库层”,以区别于应用程序框架层。
许多 Android 核心的系统组件和服务(例如 ART 和 HAL)构建自原生代码,需要以 C 和 C++ 编写的原生库。Android 平台提供的 Java 框架 API 用来向应用程序提供其中部分原生库的功能。例如,您可以通过 Android 框架的 Java OpenGL API 访问 OpenGL ES,以支持在应用中绘制和操作 2D 和 3D 图形。
总的来说,就是 Android 包含一个 C/C++库 的 集合,供 Android 系统的各个组件使用。这些功能通过 Android 的应用程序框架(application framework)暴露给开发者。即如果开发的是需要 C 或 C++ 代码的应用,可以使用 Android NDK 直接从原生代码访问某些原生平台库。
Android的NDK下载地址提供了 Android 本地 C/C++ 开发环境和工具。
Native 系统库 包括 9 个子系统:
- 系统 C 库
- 从BSD继承来的标准C系统函数库
- 专门为基于嵌入式 Linux 设备定制
- Media Manager 媒体管理
- 基于PacketVideo的OpenCORE
- 这些库支持播放和录制许多流行的音频和视频格式,以及静态图像文件,包括MPEG4、 H.264、 MP3、 AAC、 AMR、JPG、 PNG
- Surface Manager 图层管理
- 执行多个应用程序时候,负责管理显示与存取操作间的互动,另外也负责2D绘图与3D绘图进行显示合成
- LibWebCore
- Web浏览器引擎
- 驱动Android浏览器和内嵌的web视图
- SGL
- 基本的2D图形引擎库
- 3D库(OpenGL|ES)
- 基于OpenGL ES 1.0 API 标准实现的3D绘图函数库
- 即 OpenGLESate开放图形库用来支持3D效果
- FreeType —— 位图和矢量字体渲染,提供点阵字与向量字的描绘与显示
- SQLite —— 小型的关系型数据库引擎 。所有应用程序都可以使用的强大而轻量级的关系数据库引擎
- SSL —— 在Andorid上通信过程中实现握手,即 为数据通信提供支持
这里的 Native系统库 主要包括 init 孵化来的用户空间的守护进程、HAL层以及开机动画等。
启动 init 进程(pid=1),是 Linux 系统的用户进程, init 进程是所有用户进程的鼻祖。
进程加载流程:
- init进程会孵化出ueventd、logd、healthd、installd、adbd、lmkd等用户守护进程;
- init进程还启动 servicemanager(binder服务管家)、 bootanim(开机动画)等重要服务
- init进程孵化出Zygote进程,Zygote进程是Android系统的第一个Java进程(即虚拟机进程), Zygote是所有Java进程的父进程,Zygote进程本身是由init进程孵化而来的。
5.Java API Framework 层( Application Framework )
应用程序框架层又称为 “JAVA库”。应用程序框架层所提供的组件一般都是以JAVA语言编写。
一方面Java库层为上层应用程序提供了API接口;
另一方面也囊括了不少系统级服务进程的实现,是与Android应用程序开发者关系最直接的一层。开发人员可以完全访问Android系统应用程序,从而复用系统提供的框架API。
通过提供开放的开发平台,Android使开发者能够编制极其丰富和新颖的应用程序。开发者可以自由地利用设备硬件优势、访问位置信息、运行后台服务、设置闹钟、向状态栏添加通知等等,很多很多。
开发者可以完全访问和使用 Android 系统提供的框架 API。应用程序的体系结构旨在简化组件的重用,任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功能(需要服从框架执行的安全限制)。这一机制允许用户替换组件。
可以通过 Java 语言编写的 API 使用 Android OS 的整个功能集。这些 API 构成了 Android 应用所需的模块,它们可简化核心模块化系统组件和服务的重复使用。
所有的应用程序其实是一组服务和系统,Application Framework 应用程序框架层 共 包括10个部分:
- Activity Manager 活动管理 —— 管理应用程序生命周期,从安装到运行到卸载。提供通用的导航回退( 返回 )功能
- Window Manager 窗口管理
- Content Providers 内容提供者 —— 使应用程序能访问其他应用程序(如通讯录)的数据,或共享自己的数据
- View System 视图系统 —— 丰富的可扩展的视图集合,用来构建 UI 应用程序。包括包括列表、网格、文本框、按钮,甚至是内嵌的网页浏览器
- Notification Manager 通知管理 —— 使所有的应用程序能够在状态栏显示自定义提醒。
- Package Manager 包管理、
- Telephony Manager 电话管理
- Resource Manager 资源管理 —— 提供访问非代码资源,如本地化字符串、图形和布局文件
- Location Manager 位置管理器、
- XMPP Services XMPP 服务
- XMPP((Extensible Messaging and Presence Protocol,前称Jabber)是一种以XML为基础的开放式实时通信协议,XMPP网络是基于服务器的(即客户端之间彼此不直接交谈),但是也是分散式的。不像 AOL 实时通或MSN Messenger等服务,XMPP没有中央官方服务器。
- Jabber.org 的公众服务器上有大量的用户,所以有些人误解了,以为它是官方服务器,不过事实上任何人都可以在自己的域名上运行 XMPP 服务器。
- Jabber 识别符(JID)是用户登录时所使用的账号,看起来通常像一个电子邮件地址,如someone@example.com;前半部分为用户名,后半部分为XMPP服务器域名,两个字段以@符号区隔。
假设朱丽叶(juliet@capulet.com)想和罗密欧(romeo@montague.net)通话,他们两人的账号分别在Capulet.com及Montague.net的服务器上。当朱丽叶输入信息并按下发送钮之后,一连串的事件就发生了:
朱丽叶的XMPP客户端将她的信息发送到Capulet.com XMPP服务器。
Capulet.com XMPP服务器打开与Montague.net XMPP服务器的连接。
Montague.net XMPP服务器将信息寄送给罗密欧。如果他目前不在在线,那么存储信息以待稍后寄送。
进程加载流程:
- Zygote进程,是由init进程通过解析init.rc文件后fork生成的,Zygote进程主要包含:
- 加载ZygoteInit类,注册Zygote Socket服务端套接字
- 加载虚拟机
- 提前加载类preloadClasses
- 提前加载资源preloadResouces
- System Server进程,是由Zygote进程fork而来,SystemServer是Zygote孵化的第一个进程,System Server负责启动和管理整个Java framework,包含ActivityManager,WindowManager,PackageManager,PowerManager等服务。
- Media Server进程,是由init进程fork而来,负责启动和管理整个C++ framework,包含AudioFlinger,Camera Service等服务。
6.App 层
搭载Android系统的手机,有许多的应用运行在虚拟机Dalvik之上。通过这些应用,手机用户才能进行丰富的功能体验。
Android 随附一套用于电子邮件、短信、日历、互联网浏览和联系人等的核心应用。
平台随附的应用与用户可以选择安装的应用一样,没有特殊状态。因此第三方应用可成为用户的默认网络浏览器、短信 Messenger 甚至默认键盘(有一些例外,例如系统的“设置”应用)。
系统应用可用作用户的应用,以及提供开发者可从其自己的应用访问的主要功能。例如,如果用户的应用要发短信,可以直接通过系统的默认短信应用进行该服务。
系统应用程序既为用户提供日常生活中常用应用程序,又为提供开发人员提供了可以直接调用系统应用的关键功能。
搭载在系统上的应用是由应用开发工程师编写的工程代码,通过编译工具编译转化成可执行的机器码.o文件进行工作的,即 Java code → .class →.o → dex(Dalvik executable)
进程加载流程:
- Zygote进程孵化出的第一个App进程是Launcher,这是用户看到的桌面App;
- Zygote进程还会创建Browser,Phone,Email等App进程,每个App至少运行在一个进程上。
- 所有的App进程都是由Zygote进程fork生成的。
7.Syscall && JNI
- Native与Kernel之间有一层系统调用(SysCall)层,进一步了解可以参考这篇 Linux系统调用(Syscall)原理
- Java层与Native(C/C++)层之间的纽带JNI,进一步了解可以参考这篇 Android JNI原理分析