做者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!html
學習安卓的架構,是從操做系統的角度理解安卓。安卓使用Linux內核,但安卓的架構又與常見的Linux系統有很大的區別。咱們先來回顧一下傳統的Linux架構,再來看安卓的變化。java
先來看常見的Linux系統架構,你能夠參考Linux的架構android
內核是系統的底層。Linux開機後,內核即啓動,並存活於屬於本身的內存空間,即內核空間(kernel space)。內核的一大功能是和硬件通訊。內核中包含各類驅動程序,這些驅動程序既能實現底層的硬件讀寫操做,又包含硬件使用邏輯。好比一臺打印機的驅動,會把打印指令放在內存中的A位置,把打印數據放在內存中的B位置。打印機讀取指令後,會從B位置取得數據打印。在內核上層,驅動程序的功能被抽象爲函數調用,好比printx(data)。這個函數調用隱藏了許多細節,好比如何執行讀寫,以及A和B的具體位置。程序員
除了抽象硬件外,內核還維護着Linux的許多重要運行機制,好比虛擬內存、調度器、信號以及進程間通訊(IPC)。內核的功能接口是系統調用(system call)函數。數據庫
用戶使用C或者C++編寫的程序,將編譯成機器碼,運行成爲一個進程(process)。每一個進程都會有一個本身的進程空間。進程空間存活於內核空間以外的用戶空間(user space)。進程空間中包含程序的代碼和數據。不一樣進程的進程空間相互獨立。進程間若是想要相互交流,須要借用特殊的進程間通訊(IPC)機制。進程空間中有棧(stack)和堆(heap)。當執行到新的函數調用時,棧頂會增長一幀(stack frame),用於記錄該函數的數據和返回地址。當函數執行完成時,該幀會彈出,並根據返回地址接着執行母程序的指令。堆中的空間由程序自由分配。你能夠進一步參考Linux從程序到進程。編程
一個進程空間架構
Linux的程序大可能是C和C++編寫。代碼被編譯爲機器碼,以便計算機理解。經常使用的代碼被編譯成庫(library)。程序員能夠從本身的程序中調用庫函數,來重複利用已有代碼。程序中調用庫函數時,庫中包含的機器代碼會加載入程序對應的進程空間。框架
咱們如今來看看安卓的架構。Android的底層使用的是Linux內核。在用戶空間中,每一個應用也會運行爲一個進程。但安卓細節方面和傳統Linux差異很大。wordpress
HAL函數
安卓驅動硬件的方式與Linux不盡相同。傳統Linux的驅動徹底存活於內核空間。Android則在內核外部增長了硬件抽象層(HAL, Hardware Abstraction Layer),把一部分驅動功能放到HAL層中。你或許會奇怪,安卓爲何費盡麻煩增長一個HAL呢?爲了保護源代碼。Linux內核採用了GPL協議,因此硬件生產商想要支持Linux系統,必須遵守GPL協議公開硬件驅動的源代碼。但這些源代碼中包含有許多硬件的設計信息,牽涉到硬件生產商的核心利益。而增長了HAL層以後,硬件廠商就不須要開放全部的驅動代碼了。
咱們來看看HAL的具體工做方式。安卓的HAL存活在用戶空間,它與內核驅動通訊。但HAL是個「空殼」,安卓會根據須要,加載不一樣的動態庫,好比調用計算機時,載入libprinter.so。這個動態庫是由硬件廠商提供的。好比上面的打印機,硬件廠商能夠把讀寫功能作成驅動。而「指令寫入位置A、數據寫入位置B」這樣的高層邏輯,則編譯成庫文件(.so)。當咱們使用打印機打印時,咱們將打印需求和數據發送給HAL。HAL加載對應的動態庫,經過內核驅動的讀寫功能,將指令寫入打印機的內存位置A,數據寫入位置B。打印機預裝的程序從位置A讀到打印指令,就會從位置B讀取數據,實現打印。這樣,HAL實際上把部分驅動功能放入到動態庫中,內核中的驅動只保留最基本的讀寫操做功能。部分驅動功能從內核空間轉移到了用戶空間。因爲高層邏輯是編譯好的.so文件,打印機廠商不用擔憂如指令位置A、數據位置B這樣的信息泄露。
左爲Linux,右爲安卓HAL
安卓的HAL模塊是從Linux內核導出的,因此源代碼公開。HAL是Apache協議,並不要求它的配套程序,如硬件驅動的源碼公開。因爲這些庫函數沒有直接調用內核,因此不須要釋放源代碼。經過HAL層,安卓保護了硬件廠商的商業利益,鼓勵了硬件廠商對安卓系統的支持。
固然,Linux開發小組對此很不高興,把安卓的開發分支從Linux內核中刪除。
Dalvik虛擬機
安卓的應用是由Java編寫的,而包括HAL在內的Linux的庫都是由C/C++編寫的,這個落差由Dalvik虛擬機銜接的。當一個應用運行時,進程空間內將包含一個Dalvik虛擬機。Java程序編譯爲字節碼文件,運行在Dalvik虛擬機中。根據Java代碼中的要求,Dalvik經過JNI(Java Native Interface)調用底層的C/C++編寫的功能。JNI是從Java中調用C/C++模塊的接口。因爲上層接口的標準化,字節碼能夠暢通無阻的跨平臺運行。
Dalvik VM
Dalvik虛擬機內部是一個「虛擬」進程空間,有本身的棧和堆,管理代碼的運行流程。若是這以「虛擬」進程空間不足,Dalvik內建的垃圾回收(garbage collection)機制會自動清空堆上再也不使用的對象。自動的垃圾回收簡化了程序員的工做,但速度較慢。手動內存管理效率高,但須要更多的編程,且容易犯錯。垃圾回收的具體原理可參考Java內存管理與垃圾回收。
固然,Oracle不高興,認爲Dalvik是對JVM赤裸裸的抄襲。
Core Library和Android Framework
Android程序員的主要工做是編寫Dalvik上運行的Java程序。Google提供了核心類庫(Java core library),它包括Java的經常使用類庫,如:
這些類庫的API,與Oracle的官方API相同,因此你能夠按照一樣的方法調用。
核心類庫中還包括Dalvik虛擬機的調用接口:
安卓程序員還能夠調用一些針對安卓的類庫,即安卓框架(Android Framework)。這些類庫對應安卓的特定功能。經過它們,咱們能夠操縱安卓上的各個功能模塊,從觸屏到GPS,從視圖元素到數據庫。如:
核心類庫和安卓框架是安卓程序員的左膀右臂。再加上Java語言自己的邏輯,這就是安卓程序員戰鬥着的世界了。我會在之後的文章中,繼續深刻這個戰場。
多謝微博 @文藝復興記 指導我Dalvik的相關內容。下面資料也幫助了我理解:
http://sujaiantony.wordpress.com/2012/06/25/an-android-101-hardware-and-hal/
HAL
Dalvik
Core Library
Android Framework
歡迎繼續閱讀「Java快速教程」系列文章