(摘录一本书中的部分章节,对理解整个Android系统的架构有帮助,转载如下。)

1.1.1 Android 的系统构架
要深入学习 Android,首先需要学习 Android的系统构架。Android的系统构架和其操作系统一样,采用了分层的构架,层次非常清晰,因此要掌握它的构架并不难。下图为为Android 的系统构架图,如果你对该图已经不陌生,并且理解图中所示的构架,那么你可以跳过这部分内容(或者快速浏览) ;如果你是第一次见到该图,建议你详细阅读该部分内容,因为整本书的内容都是以这幅图为基础的。我们会对图中的每一个模块进行详细地分析,让你真正掌握 Android 的技术内幕。

Android系统框架和几种调用流程_第1张图片
Android 分为五层,从高层到低层分别是应用程序层(Applications) 、应用程序框架层(Application Framework) 、系统运行库层(Libraries和 Android Runtime)和 Linux内核层(Linux Kernel) 。下面分别来看各个层次为我们提供了什么功能,以及如何来运用这些功能。
1.应用程序层
Android会与核心应用程序包一起发布, 该应用程序包包括图1为大家展示的主屏 (Home) 、E-mail 客户端、SMS/MMS短消息程序、日历、地图、浏览器、联系人管理程序等。所有的应用程序都是使用 Java语言编写的,通过调用应用程序框架层(Application Framework)所提供的 API来完成。当然,你也可以使用 Java通过 JNI的方式,配合 Android NDK来开发原生的应用程序,这样可以提高应用程序的效率,但是难度也大大增加——你需要精通C和 C++等语言,并且对 Android NDK所提供的为数不多的功能有很深的认识。因为 Android NDK提供的功能不是太多,为了避免你做了很久之后才发现——原来 NDK 不支持某项功能,大家可以根据自己的需求来选择是否采NDK 开发原生程序。
2.应用程序框架层
应用程序框架层为开发人员提供了可以完全访问核心应用程序所使用的 API 框架。该应用程序的构架设计简化了组件的重用,任何一个应用程序(以及任何其他应用程序)都可以发布自己的功能模块(在遵循框架的安全性限制的前提下) 。同样,该应用程序重用机制也使用户可以方便地替换程序组件。 下面来看一下该层的每一个模块为我们提供的组件, 如表 1-1所示。

3.系统运行库层
系统运行库层包括程序库和 Android 运行库两部分,下面分别来介绍这两个部分。
(1)程序库
Android 包含一些 C/C++库,这些库能被 Android 系统中的不同组件使用,它们通过应用程序框架为开发者提供服务,表 1-2 给出了这些核心库的功能介绍。

Android系统框架和几种调用流程_第2张图片

(2)Android 运行时库
从图 1 可以看出,Android 运行时库又分为核心库和 Dalvik 虚拟机两部分。核心库提供了Java语言核心库的大多数功能, 这里主要通过JNI的方式向应用程序框架层提供调用底层程序库的接口。Dalvik 虚拟机是为了能同时高效地运行多个 VMs 而实现的。Dalvik 虚拟机执行.dex 的Dalvik可执行文件,该格式的文件针对最小内存使用做了优化。Dalvik虚拟机是基于寄存器的,所有的类都经由Java汇编器编译,然后通过SDK中的dx工具转化成.dex格式并由虚拟机执行。Dalvik虚拟机依赖Linux的一些功能,比如线程机制和底层的内存管理机制。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的 Dalvik 虚拟机实例。关于这部分内容,先简单向大家介绍到这里,后面会给大家详细分析 Android SDK 工具包和 Dalvik 虚拟机。
4.Linux内核层
Android依赖于 Linux 2.6 版内核提供的核心系统服务,例如安全、内存管理、进程管理、网络栈、驱动模块等。内核作为一个抽象层,存在于软件栈层和硬件层之间,Android 对内核进行了增强,主要表现在以下几个方面:

Android系统框架和几种调用流程_第3张图片

到这里, 我们对 Android系统构架的分析就告一段落了, 你现在至少应该明白整个 Android系统的构架和每个模块的功能, 以便为后面的深入学习打下基础。 Android系统是如何启动的?启动过程中需要初始化什么内容?如果你不知道(或不完全知道)这些问题的答案,不必担心,下一小节将剖析 Android 系统启动时的初始化操作。

1.1.2 Android 的初始化流程
上一小节分析了 Android的系统构架,让大家对 Android系统有了一个深入的认识;但是,Android 系统本身非常庞大,在深入分析每个模块的具体功能之前,有必要对其启动过程进行分析。我们需要了解这么一个庞大的系统在启动的时候需要执行哪些初始化操作。 Android 系统在启动时首先会启动 Linux 基础系统,然后引导加载 Linux Kernel 并启动初始化进程(Init) ,如图 1-1 所示。

接着,启动 Linux守护进程(daemons) 。这个过程主要需要启动以下内容,如图 1-2所示。
‰ 启动 USB守护进程(usbd)来管理 USB连接。
‰ 启动 Android Debug Bridge守护进程(adbd)来管理 ADB连接。
‰ 启动 Debug 守护进程(debuggerd)来管理调试进程的请求(包括内存转换等) 。
‰ 启动无线接口守护进程(rild)来管理无线通信。

在启动 Linux守护进程的同时还需要启动 Zygote进程,如图 1-3所示。它主要包括以下需要启动和注册的内容:
‰ 初始化一个 Dalvik 虚拟机实例。
‰ 装载 Socket请求所需的类和监听。
‰ 创建虚拟机实例来管理应用程序的进程。

Android系统框架和几种调用流程_第4张图片

再接着,需要初始化 runtime 进程,初始化过程如图 1-4 所示。在这个过程中需要处理以下操作:
‰ 初始化服务管理器。
‰ 注册服务管理器,以它作为默认 Binder 服务的 Context管理器。

runtime 进程初始化之后,runtime 进程将发送一个请求到 Zygote,开始启动系统服务,这时 Zygote 将为系统服务进程建立一个虚拟机实例,并启动系统服务,如图 1-5 所示。

Android系统框架和几种调用流程_第5张图片

紧接着,系统服务将启动原生系统服务,主要包括 Surface Flinger和Audio Flinger。这些本地系统服务将注册到服务管理器(Service Manager)作为 IPC服务的目标,如图 1-6所示。

Android系统框架和几种调用流程_第6张图片

系统服务将启动 Android 管理服务,Android 管理服务将都被注册到服务管理器上,如图1-7 所示。

Android系统框架和几种调用流程_第7张图片

最后,当系统加载完所有的服务之后会处于等待状态,等待程序运行。但是,每一个应用程序都将启动一个单独的进程。如图 1-8 所示,系统启动了一个 Home 进程和一个 Contacts 进程。那么,各个进程之间如何进行交互呢?这就需要使用 IPC机制了,后面会详细介绍。

到这里, 系统的整个启动过程就结束了, 可以在上面运行应用程序了。 你也应该对Android系统启动过程的每一步都有了深入的理解。实际上,这个启动过程就是从 Android系统构架图中最底层的 Linux内核层一步一步加载和注册到应用程序框架层,最终在应用程序层运行我们自己的应用程序。那么,各个层次之间又有什么样的关系呢?应用程序在最上层又是如何调用到最底层的核心服务的呢?下一小节将为大家分析各个层次之间的关系。

1.1.3 各个层次之间的相互关系
上一小节介绍了 Android 系统的启动过程,本小节将介绍 Android 应用程序是如何按照层次关系来调用最底层的硬件和服务的。如果你对上一节的内容理解得还不够深入,那么可以回去再仔细地看一遍,这样才能更好地理解本小节的内容。好的,相信你已经准备好了,开始吧。在 Android 中运行的应用程序都是通过以下三种方式来层层深入的:
‰ App→Runtime Service→Lib
‰ App→Runtime Service→Native Service→Lib
‰ App→Runtime Service→Native Daemon→Lib
下面就分别来分析这三种方式,我们还是采用流程图的方式来为大家展示。
App→Runtime Service→Lib 方式对应的流程图如图 1-9 所示。

Android系统框架和几种调用流程_第8张图片

通过图1-9我们可以看出, 在Android平台上, 应用程序首先是在应用程序层通过Binder IPC调用应用程序框架层的 Runtime Service,然后再通过 JNI与运行库中的原生服务绑定,并动态地加载 Hal库,进而调用 Linux内核层的Kernel Driver。为了便于大家更好地理解,我们通过一个实例(Location Manager)来为分析该流程,如图 1-10 所示。

以上就是第一种方式的调用过程,接下来我们再看一下第二种方式(App→Runtime Service→Native Service→Lib)是如何调用的。这种方式通常被 Android原生服务所采用,同样先看一下调用流程图,如图 1-11 所示。

Android系统框架和几种调用流程_第9张图片

图 1-11为我们展示了 Android原生服务的调用流程,可以看出,与第一种方式相比,只多了一个通过 IPC机制调用原生服务并进行动态装载的过程。所以,这里我们就不再重复介绍,但还是给出一个 Audio 的例子,如图 1-12 所示。

Android系统框架和几种调用流程_第10张图片

从图 1-12 可以看出,应用程序调用了应用程序框架层的 MediaPlayer,然后调用系统运行库层的 MediaPlaye。这时MediaPlaye又分别调用了 Media Framework和 AudioFlinger,而后通过 AudioFlinger 调用指定的库(libaudio.so) ,最后才调用到 Kernel Driver。 下面来看一下最后一种方式“App→Runtime Service→Native Daemon→Lib” ,如图 1-13所示。这种方式通常用于守护进程的连接。

从图 1-13可以看出,这种方式比原生服务的调用更简单,它直接通过 JNI绑定原生服务,再通过 sockets调用守护进程进行动态加载。 下面就来看一个简单的例子, 电话管理 (Telephony Manager)的调用就是这样一个原生的守护进程调用,其流程如图 1-14 所示。

这个调用的过程非常简单,相信图 1-14 已经表述得足够清楚了。
1.1.4 Android 系统开发(移植)和应用开发
通过前面的学习,我们了解到 Android 是一个庞大且完善的系统,我们可以基于 Android来进行哪些开发工作?每一种开发工作又有什么不同?不同的开发工作需要掌握的技术有什么差异?学完本小节的内容你就会知道应该如何利用 Android 来开发自己所需要的产品。 因为 Android 是一个开源的操作系统,所以可以选择的开发方式主要有以下两种:
‰ Android 系统开发(移植)
‰ Android 应用开发
1.Android系统开发(移植)
Android 系统开发(移植)属于底层的开发工作,主要针对 Android 系统本身进行完善和将其移植到其他的硬件平台,因此需要掌握 Android 系统构架中的 Linux 内核层和系统运行库层,如图 1-15 所示。 Android系统开发主要涉及 Libraries和 Android Runtime 这两部分内容, 一般就是在本地编写 C/C++代码,然后通过 JNI 向上层提供调用接口,主要是为应用开发提供服务等工作。Android 系统移植则主要涉及硬件抽象层和 Linux 内核层,移植的主要工作是将驱动移植到不同的硬件上,使其能完美地运行Android 系统。这些驱动又主要包括设备驱动和 Android专用驱动。

Android系统框架和几种调用流程_第11张图片

无论是系统开发还是系统移植, 都是由底层直接操作 Android的源代码, 因此在开发之前,我们首先就需要准备 Android 的源码。下一节将向大家详细介绍如何获取和编译 Andorid 的源码,以及 Android 源码的结构。
2.Android应用开发
Android 应用开发主要是根据 Android 系统所提供的 API 来完成各种应用程序的编写,所使用的API属于Android的应用框架层, 如图1-16所示。 如果Android系统没有提供某些API,那么只能通过在 Android 系统底层编写 C/C++代码来开发这些 API 并向 Android 应用框架层提供接口。但是笔者不建议这样做,因为这很可能会导致你的应用程序与其他 Android 系统不兼容。

我们自己所开发出来的应用程序与应用层的应用程序运行在同一个层次上,因此再次提醒大家,开发应用时一定要遵循 Android API 框架的规定,以避免开发的应用程序不兼容。 另外,应用开发属于上层开发,不需要接触底层的 C/C++代码,所以,开发前我们只需要准备 Android SDK 和模拟器即可(当然,你可能也需要使用一款 IDE,推荐使用 Eclipse) 。最后,Android SDK 既可以通过编译源码获得,也可以在 Android 的官方网站下载编译好的SDK。下面将讲解如何通过编译源码的方式来取得 Android SDK,以及 SDK 的结构和开发工具包。



更多相关文章

  1. 分享自己在项目中对android文件系统的一些认识
  2. Android帮助文档翻译——开发指南(一)应用程序基本原理
  3. 无废话Android之android下junit测试框架配置、保存文件到手机内
  4. 用Android LiveCD体验Android 操作系统的魅力
  5. 真正的机器人操作系统---Android
  6. Android 应用程序基础(Application Fundamentals)
  7. 《Android系统学习》第八章:Android gtest
  8. Ubuntu-18.04 LTS配置android系统源码编译环境

随机推荐

  1. c语言中什么是逗号运算符并举例
  2. strcpy函数的作用是什么?
  3. C++如何简单输出当前日期时间
  4. c语言中合法标识符有哪些
  5. C语言有几种注释方式
  6. C++在构造函数中使用new时,需要注意这些事
  7. 在什么语言中字符串以\0标志字符串的结
  8. 声明动态数组的语句怎么写
  9. 详解C++虚成员函数和动态联编
  10. c语言中文本输出的函数名称是什么?