Linux系统架构我们先来看看常见的Linux系统架构。可以参考Linux架构。内核是系统的底层。Linux开机后,内核启动并存活在自己的内存空间,即内核空间(kernelspace)。内核的一个主要功能是与硬件进行通信。内核包含了各种驱动程序,不仅可以实现底层的硬件读写操作,还包括硬件使用逻辑。例如,打印机的驱动程序会将打印命令放在内存中的A位置,而将打印数据放在内存中的B位置。打印机读取命令后,会从B位置获取数据进行打印。在内核的上层,驱动的功能被抽象成函数调用,如printx(data)。这个函数调用隐藏了许多细节,比如读写是如何执行的,以及A和B的确切位置。内核除了对硬件进行抽象,还维护着Linux的许多重要运行机制,如虚拟内存、调度器、信号、进程间通信(IPC)等。内核的功能接口就是系统调用(systemcall)函数。用户用C或C++编写的程序将被编译成机器码并作为一个进程运行。每个进程都会有自己的进程空间。进程空间存在于内核空间之外的用户空间(userspace)中。进程空间包含程序的代码和数据。不同进程的进程空间相互独立。如果进程之间要进行通信,就需要借用一种特殊的进程间通信(IPC)机制。进程空间中有栈(stack)和堆(heap)。当执行新的函数调用时,会在栈顶增加一个帧(stackframe)来记录函数的数据和返回地址。当函数执行完成后,会弹出框架,根据返回地址执行父程序的指令。堆中的空间由程序自由分配。您可以进一步参考Linux从程序到进程。Linux程序主要是用C和C++编写的。代码被编译成机器代码,以便计算机可以理解它。常用的代码被编译成库(library)。程序员可以从自己的程序中调用库函数来重用现有代码。当程序调用库函数时,库中包含的机器码会被加载到程序对应的进程空间中。Android架构现在让我们看看Android架构。Android底层使用Linux内核。在用户空间中,每个应用程序也作为一个进程运行。但是Android的细节和传统的Linux有很大的不同。HALAndroid驱动硬件的方式与Linux不同。传统的Linux驱动程序完全存在于内核空间中。Android在内核外增加了一个硬件抽象层(HAL,HardwareAbstractionLayer),将一些驱动函数放在了HAL层。你可能会疑惑,为什么Android不厌其烦地添加一个HAL呢?为了保护源代码。Linux内核采用GPL协议,所以硬件厂商想要支持Linux系统就必须按照GPL协议公开硬件驱动的源代码。但这些源代码中包含了大量的硬件设计信息,涉及硬件厂商的核心利益。加入HAL层后,硬件厂商无需开放所有驱动代码。让我们详细了解一下HAL是如何工作的。Android的HAL位于用户空间,它与内核驱动程序进行通信。但HAL是一个“空壳”。Android会根据需要加载不同的动态库,比如调用电脑时加载libprinter.so。该动态库由硬件厂商提供。例如,对于上面的打印机,硬件厂商可以将读写功能做成一个驱动程序。并将“命令写入位置A,数据写入位置B”等高层逻辑编译成库文件(.so)。我们在使用打印机进行打印时,将打印需求和数据发送给HAL。HAL加载相应的动态库,通过内核驱动的读写函数,将指令写入打印机的内存位置A,将数据写入位置B。当打印机预装的程序从A位读取打印命令时,会从B位读取数据实现打印。这样一来,HAL实际上是将一些驱动函数放到了动态库中,内核中的驱动只保留了最基本的读写操作函数。部分驱动程序功能已从内核空间移至用户空间。由于高层逻辑是一个编译好的.so文件,打印机厂商无需担心命令位A、数据位B等信息泄露。Android的HAL模块是从Linux内核导出的,所以源代码是开放的。HAL是一种Apache协议,不需要公开其配套程序,如硬件驱动程序的源代码。由于这些库函数不直接调用内核,所以不需要发布源代码。Android通过HAL层保护硬件厂商的商业利益,鼓励硬件厂商支持Android系统。当然,Linux开发团队对此并不高兴,将Android开发分支从Linux内核中移除。Android的HAL模块是Linux内核导出的,所以源代码是开放的。HAL是一种Apache协议,不需要公开其配套程序,如硬件驱动程序的源代码。由于这些库函数不直接调用内核,所以不需要发布源代码。Android通过HAL层保护硬件厂商的商业利益,鼓励硬件厂商支持Android系统。当然,Linux开发团队对此并不高兴,将Android开发分支从Linux内核中移除。Dalvik虚拟机Android应用程序是用Java编写的,而包括HAL在内的Linux库是用C/C++编写的。这个差距由Dalvik虚拟机弥补。当应用程序运行时,进程空间将包含一个Dalvik虚拟机。Java程序被编译成字节码文件并在Dalvik虚拟机中运行。根据Java代码中的需求,Dalvik通过JNI(JavaNativeInterface)调用底层C/C++编写的函数。JNI是用于从Java调用C/C++模块的接口。由于上层接口的标准化,字节码可以畅通无阻的跨平台Dalvik虚拟机内部是一个“虚拟”的进程空间,有自己的栈和堆,管理着代码的运行过程。如果这意味着“虚拟”进程空间不足,Dalvik内置的垃圾收集(garbagecollection)机制会自动清空堆上不再使用的对象。自动垃圾收集简化了程序员的工作,但速度较慢。手动内存管理是高效的,但需要更多的编程并且容易出错。垃圾回收的具体原理可以参考Java内存管理和垃圾回收。Oracle当然不高兴了,认为Dalvik是对JVM的明目张胆的抄袭。CoreLibrary和AndroidFrameworkAndroid程序员的主要工作是编写运行在Dalvik上的Java程序。Google提供了一个核心类库(Javacorelibrary),里面包含了常见的Java类库,比如:java.langjava.utiljava.mathjava.net...这些类库的API和Oracle官方的API是一样的,所以你可以用同样的方式调用它。核心类库还包括Dalvik虚拟机的调用接口:dalvik.annotationdalvik.bytecodedalvik.systemAndroid程序员也可以调用一些Android特有的类库,即AndroidFramework。这些类库对应着Android的具体功能。通过它们,我们可以操作Android上的各种功能模块,从触摸屏到GPS,从视图元素到数据库。如:android.databaseandroid.bluetoothandroid.gesture...Android相关类库列表核心类库和Android框架是Android程序员的得力助手。再加上Java语言本身的逻辑,这就是Android程序员拼搏的天下。我将在以后的文章中继续深入研究这个战场。感谢微博@renairenji指导我了解Dalvik相关内容。以下信息也帮助我理解:http://sujaiantony.wordpress.com/2012/06/25/an-android-101-hardware-and-hal总结HALDalvikCoreLibraryAndroidFramework
