1. 程式人生 > >Android系統移植與平臺開發(七)- 初識HAL

Android系統移植與平臺開發(七)- 初識HAL

1.      HAL的module與stub

HAL(Hardware AbstractLayer)硬體抽象層是Google開發的Android系統裡上層應用對底層硬體操作遮蔽一個軟體層次,說白了,就是上層的應用不用關心底層硬體具體如何工作的,只要向上層提供一個統一的介面即可,這種設計思想廣泛的存在於當前的軟體架構設計裡。

嚴格來講,Android系統裡完全可以沒有HAL硬體抽象層,上層應用層可以通過API呼叫到底層硬體,但是Android自出現開始一直打著開源的旗號,而一些硬體廠商由於商業因素,不希望自己的核心程式碼開源出來,而只是提供二進位制程式碼。另外,Android系統裡使用的一些硬體裝置介面可能不是使用的Linux Kernel的統一介面,並且還有GPL版權的原因,所以Google不利己,在Android的架構裡提出了HAL的概念,這個HAL其實就是硬體獨立的意思,Android系統不依賴於某一個具體的硬體驅動,而是依賴於HAL程式碼,這樣,第三方廠商可以將自己不開源的程式碼封裝在HAL層,僅提供二進位制。

HAL的架構分為兩種:

Ø  舊的架構module

Ø  新的架構modulestub

舊的架構比較好理解,Android使用者應用程式或框架層程式碼由Java實現,Java執行在Dalvik虛擬機器中,沒有辦法直接訪問底層硬體,只能通過呼叫so本地庫程式碼實現,在so本地庫程式碼裡有對底層硬體操作程式碼,如下圖所示:


也就是說,應用層或框架層Java程式碼,通過JNI技術呼叫C或C++寫的so庫程式碼,在so庫程式碼中呼叫底層驅動,實現上層應用的提出的硬體請求操作。實現硬體操作的so庫為:module。

其實現流程如下圖:


由此可見,Java程式碼要訪問硬體效率其實挺低的,沒有C程式碼效率高,但是Android系統在軟體框架和硬體處理器上都在減少和C程式碼執行效率的差距,據國外測試的結果來看,基本上能達到C程式碼效率的95%左右。

這種設計架構雖然滿足了Java應用訪問硬體的需要,但是,使得我們的程式碼上下層次間的耦合太高,使用者程式或框架程式碼必須要去載入module庫,如果底層硬體有變化,moudle要重新編譯,上層也要做相應的變化,另外,如果多個應用程式同時訪問硬體,都去載入module,同一module被多個程序對映多次,會有程式碼的重入問題。因此,Google又提出了新的HAL架構。


1.2 新的HAL架構


新的架構使用的是module stub方式。Stub是存根或樁的意思,其實說白了,就是指一個物件代表的意思。由上面的架構可知,上層應用層或框架層程式碼載入so庫程式碼,so庫程式碼我們稱為module,在HAL層註冊了每個硬體物件的存根stub,當上層需要訪問硬體的時候,就從當前註冊的硬體物件stub裡查詢,找到之後stub會向上層module提供該硬體物件的operations interface(操作介面),該操作介面就儲存在了module中,上層應用或框架再通過這個module操作介面來訪問硬體。如下圖,以Led為例的示意圖:

 

Led App為Android 應用程式,Led App裡的Java程式碼不能操作硬體,將硬體操作工作交給本地module庫 led_runtime.so,它從當前系統中查詢Led Stub,查詢到之後,Led Stub將硬體驅動操作返回給module,Led App操作硬體時,通過儲存在module中的操作介面間接訪問底層硬體。

問題來了:

Ø  麻煩,覺得比module方式複雜

Ø  硬體物件怎樣註冊為stub?

Ø  上層如何查詢硬體物件的stub?

“麻煩”是確定的,但是Google這麼聰明的公司不可能是光製造麻煩的公司,肯定是考慮到其它的優越性才使用這種方式。

在Module架構中,原生代碼由so庫實現,上層直接將so庫對映進程序空間,會有程式碼重入及裝置多次開啟的問題。新的Stub框架雖然也要載入module庫,但是這個module已經不包含操作底層硬體驅動的功能了,它裡面儲存的只是底層Stub提供的操作介面,底層Stub扮演了“介面提供者”的角色,當Stub第一次被使用時載入到記憶體,後續再使用時僅返回硬體物件操作介面,不會存在裝置多次開啟問題,並且由於多程序訪問時返回的只是函式指標,程式碼沒有重入問題。