目前,互連網行業正在朝著移動互連網方向強勁地發展,而移動互連網的發展離不開背後的移動平台的支撐。眾所周知,如今在移動平台市場上,蘋果的 iOS、Google的Android和微軟的Windows Phone系統已經形成了三足鼎立的形勢,而Android系統的市場佔有率是最高的。Android系統之所以能夠在市場上佔據著第一的位置,一來是因 為它依託著Google的品德效應和技術實力,二來是因為它是開放的,任何人都可以得到它的原始碼,並且能夠自由地使用它。既然Android系統是開放的,作為 一個移動平台開發人員來說,當然希望能夠深入地去分析和研究它的原始碼了,然而,Android系統的原始碼非常龐大,我們需要循序漸進地去學習。
工欲善其事,必先利其器。為了全面、深入地理解Android系統的原始碼,在正式進入Android系統原始碼的世界前,我們手頭上需要準備好一些參考資料以及實驗環境,此外,還需要瞭解Android系統的架構知識。
參考資料
Android系統的原始碼非常龐大和複雜,我們不能貿然進入,否則很容易在裡面迷入方向,進而失去研究它的信心。我們應該在分析它的原始碼之前學習好一些理論知識,下面就介紹一些與Android系統相關的資料。
我們知道,Android系統是基於Linux核心來開發的,在分析它在執行階段程式庫層的原始碼時,我們會經常碰到諸如管道(pipe)、通訊端 (socket)和虛擬檔案系統(VFS)等知識。此外,Android系統還在Linux核心中增加了一些專用的驅動程式,例如用於日誌系統的 Logger驅動程式、用於處理序間通訊的Binder驅動程式和用於輔助記憶體管理的匿名共用記憶體Ashmem驅動程式。在分析這些Android專用驅動 程式的時候,也會碰到Linux核心中與進程、記憶體管理相關的資料結構。因此,我們有必要掌握一些Linux核心的基礎知識,下面就介紹四本典經的 Linux核心書籍。
- Linux Kernel Development.
這本書的作者是Robert Love,目前最新的版本是第3版。這本書對Linux核心的設計和實現提供了一個總覽視圖,從概念上對Linux核心的各個子系統的設計目標和實現思路 進行了清晰的描述,非常適合初學者閱讀。如果從軟體工程的角度來看,這本書就相當於是Linux核心的概要設計文檔。
- Understanding the Linux Kernel.
這本書的作者是Daniel P. Bovet和Marco Cesati,目前最新的版本是第3版。這本書對Linux核心的實現提供了更多的細節,詳細地描述了核心開發中用到的重要資料結構、演算法以及編程技巧, 非常適合中進階讀者閱讀。如果從軟體工程的角度來看,這本書就相當於是Linux核心的詳細設計文檔。
- Linux Device Drivers.
這本書的作者是Jonathan Corbet, Alessandro Rubini和Greg Kroah-Hartman,目前最新的版本是第3版。這本書更加註重實際操作,它詳細地講解了Linux核心驅動程式的實現原理和實現方法,讀者可以跟 著它來實際地編寫出自己的Linux驅動程式。閱讀了這本書之後,對我們後續去分析Android的專用驅動程式是有非常大的協助的。
- Linux核心原始碼情景分析
這本書的作者是毛德操和胡希明,是中國人自己編寫的一本經典的Linux核心書籍。這本書最大的特點是從使用情景出發,對Linux核心的原始碼作了詳細的分析,協助讀者把枯燥無味的原始碼給理順了。
掌握了Linux核心的基礎知識之後,還不宜馬上就去分析Android系統的原始碼,因為這樣做是漫無目的的,我們應該帶著問題或者目標去分析 Android系統的原始碼。要把問題或者目標挖掘出來,最好的方法就莫過於是在Android平台上編寫自己的應用程式了。通過編寫應用程式,我們可以 知道Android平台都提供了哪些功能,進而我們就會想去瞭解這些功能是怎麼實現的,這樣就可以達到帶著問題或者目標去分析Android系統的原始碼 了。這裡介紹兩個Android應用程式開發教程的書籍:
- Professional Android 2 Application Development.
- Google Android SDK開發範例大全.
這兩本書都使用了大量的例子來說明如何使用Android SDK來開發Android應用程式。讀者可以根據實際情況來練習一下,主要掌握Android應用程式四大組件(Activity、Service、 Broadcast Receiver和Content Provider)的用法,因為Android系統的整個架構和實現就是為了向開發人員提供這四大組件來實現各種各樣的應用程式的。在學習的過程中,如果遇 到其它問題,還可以參考官方文檔,其網址為:http://developer.android.com/index.html
環境搭建
開發Android應用程式可以在兩種環境下進行,一是在Android SDK環境下進行,一般是整合在Eclipse裡面進行開發,二是在Android原始碼工程環境下進行,在這種環境進行開發的好處是可以使用一些在 SDK中不公開的介面。但是如果我們要修改Android系統的原始碼,或者為Android系統增加新的功能介面,那麼就只能在Android原始碼工 程環境下進行了。由於我們的目的是對Android系統原始碼進行分析,因此,我們在開發Android應用程式時,也在Android原始碼環境下進 行。這樣,我們就需要搭建一套Android原始碼工程環境了。
目前,Android原始碼工程環境只能在Linux平台上使用,而Linux系統的發行版本比較多,這裡我們推薦Ubuntu系統。Ubuntu系統是免費的,而且非常便於使用,安裝和更新應用程式也非常方便,它的官方為:http://www.ubuntu.com/
安裝好Ubuntu系統之後,我們就可以在上面下載、編譯和安裝Android原始碼了,具體方法和步驟可以參考下面這篇文章:在Ubuntu上下載、編譯和安裝Android最新原始碼
Android系統的原始碼工程預設是不包含Linux核心原始碼的,如果我們需要修改Android系統的核心或者在裡面增加新的模組,那麼就要把Android核心原始碼一起下載、編譯和安裝了,具體方法和步驟可以參考下面這篇文章:在Ubuntu上下載、編譯和安裝Android最新核心原始碼(Linux Kernel)
Android原始碼工程環境搭建好了之後,我們就可以在裡面開發新的應用程式或者修改系統代碼了。增加了新的應用程式或者修改了系統的代碼之後,不需要重新編譯整個原始碼工程,只要單獨編譯有改動的模組就可以了,具體方法可以參考下面這篇文章:如何單獨編譯Android原始碼中的模組
對於已經開發好的應用程式或者系統功能,如果想把當作Demo展示給客戶來體驗時,我們既可以在真機上面運行,也可以在模擬器(Android源代 碼工程環境或者Android SDK環境都整合了模擬器)上面運行。當我們手頭上沒有真機,而且我們又不想把整個Android原始碼工程環境或者Android SDK環境帶去展示我們的Demo時,就可以考慮把模擬器這兩個環境中獨立出來了,具體方法可以參考下面這篇文章:製作可獨立分發的Android模擬器
系統架構
Android系統是按層次、分模組來設計的。在我們著手對Android系統的原始碼進行分析前,需要對Android系統的架構有一個總體的認 識,這樣我們就能夠快速地知道哪些代碼位於哪個層次上的哪個模組中,節省搜尋代碼的時間,把更多的精力投入在原始碼的分析上去。
整個系統劃分核心空間和使用者空間兩部分。核心空間包含了進程管理、記憶體管理以及裝置驅動程式模組等,其中Android專用驅動Binder、 Logger和Ashmem就是在核心空間實現的。使用者空間包含了硬體抽象層(HAL)、外部庫和執行階段程式庫層(External Libraries & Android Runtime)、應用程式架構層(Application Framework)和應用程式層(Applications)四個層次。我們應該如何去掌握這個階層呢?最好的方法就是從學習Android的硬體 抽象層作為切入點了。
可能讀者會覺得比較奇怪,為什麼要把Android系統的硬體抽象層作為學習Android系統架構的切入點呢?這個層次因為涉及到硬體,看起來這 是一個比較複雜和深奧的知識點。其實不然,Android系統的硬體抽象層在實現和使用上,層次都是非常清晰的,它從上到下涵蓋了Android系統的用 戶空間和核心空間。核心空間主要就是涉及到硬體驅動程式,而使用者空間就涉及到了Android系統應用程式層、應用程式架構層和系統執行階段程式庫層的相關知 識。因此,學習Android系統的硬體抽象層,可以使讀者快速地認識整個Android系統,從而對Android系統得到一個感性的認識,為後面深入 分析Android系統的原始碼打下良好的基礎。
Android硬體抽象層的學習可以參考下面的一系列文章:
- Android硬體抽象層(HAL)概要介紹和學習計劃
- 在Ubuntu上為Android系統編寫Linux核心驅動程式
- 在Ubuntu上為Android系統內建C可執行程式測試Linux核心驅動程式
- 在Ubuntu上為Android增加硬體抽象層(HAL)模組訪問Linux核心驅動程式
- 在Ubuntu為Android硬體抽象層(HAL)模組編寫JNI方法提供Java訪問硬體服務介面
- 在Ubuntu上為Android系統的Application Frameworks層增加硬體訪問服務
- 在Ubuntu上為Android系統內建Java應用程式測試Application Frameworks層的硬體服務
學會了編寫基本的Android應用程式並且對Android系統的整體架構有一個大概的瞭解之後,我們就可以去分析Android系統的原始碼了。
在分析Android原始碼的過程中,我們經常進入到應用程式架構層去分析它的原始碼,而在應用程式架構層中,有一部分代碼是使用C++來實現的, 這時候就會經常碰到智能指標,因此,我們把Android系統中的智能指標也作為一個基礎知識點來學習。相信使用過C++語言來做開發的讀者對智能指標不 會感到陌生。用C++來寫代碼最容易出錯的地方就是指標了,一旦使用不當,輕則造成記憶體流失,重則造成系統崩潰,因此,系統為我們提供了智能指標,避免出 現上述問題。
在Android系統中,提供了三種類型的智能指標,分別是輕量級指標、強指標和弱指標,它們都是基於對象引用計數技術來實現的。輕量級指標的計數 技術比較簡單,只要對象的引用計數值為0,它就會被釋放。強指標和弱指標的計數技術相對比較複雜,一個對象可以同時被強指標和弱指標引用,但是這個對象的 生命週期一般只受強指標的控制,即當這個對象的強引用計數為0的時候,這個對象就被釋放了,即使這時候這個對象的弱引用計數不為0。引進強指標和弱指標這 種複雜的引用計數技術是為瞭解決垃圾收集(Garbage Collection)問題而提出的。考慮這樣的一個情境,系統中有兩個對象A和B,在對象A的內部引用了對象B,而在對象B的內部也引用了對象A。當兩 個對象A和B都不再使用時,垃圾收集系統會發現無法回收這兩個對象的所佔據的記憶體的,因為系統一次只能收集一個對象,而無論系統決定要收回對象A還是要收 回對象B時,都會發現這個對象被其它的對象所引用,因而就都回收不了,這樣就造成了記憶體流失。如果採用強指標和弱指標技術,這個問題就迎刃而解了,即A和 B都用弱指標來引用對方。Android智能指標的學習,可以參考下面這篇文章: Android系統的智能指標(輕量級指標、強指標和弱指標)的實現原理分析
掌握了本文所介紹的這些基礎知識後,我們就可以正式開始分析Android系統的原始碼了。
作者:羅昇陽 原文連結:http://www.infoq.com/cn/articles/lsy-android-base