我們知道,在Android系統中,每一個應用程序都運行在獨立的進程中,這也保證了當其中一個程序出現異常而不會影響另一個應用程序的正常運轉。在許多情況下,我們activity都會與各種系統的service打交道,很顯然,我們寫的程序中activity與系統service肯定不是同一個進程,但是它們之間是怎樣實現通信的呢?Binder是android中一種實現進程間通信(IPC)的方式之一。
了解Binder
1.binder用來做什麼?用來實現不同進程之間的通信。
2.Binder是什麼?binder屬於一個驅動,工作在linux層面,運行在內核態,它的操作完成是基於一段內存。所以我們開發的程序中對binder的使用都是通過系統的調用來完成的。
3.binder是怎樣實現進程通信的?我們來通過Binder的架構來了解它實現進程間通信(IPC)的過程。
Binder架構由服務端,binder驅動,客戶端三個部分構成。如圖所示。
其中服務端,客戶端處在用戶空間,而binder驅動處在內核空間。
服務器端。一個Binder服務器端就是一個Binder類的對象。當創建一個Binder對象後,內部就會開啟一個線程,這個線程用於接收binder驅動發送的信息,收到消息後,會執行相關的服務代碼。、
Binder驅動。當服務端成功創建一個Binder對象後,Binder驅動也會相應創建一個mRemote對象,該對象的類型也是Binder類。客戶就可以借助這個mRemote對象來訪問遠程服務。
客戶端。客戶端要想訪問Binder的遠程服務,就必須獲取遠程服務的Binder對象在binder驅動層對應的mRemote引用。當獲取到mRemote對象的引用後,就可以調用相應Binder對象的服務了。
在這裡,我們可以看到,客戶端是通過Binder驅動來調用服務端的相關服務。首先,在服務端創建一個Binder對象,然後相應在Binder驅動中創建一個Binder對象,接著客戶端通過獲取Binder驅動中Binder對象的引用來調用服務端的服務。在Binder機制中正是借著Binder驅動將不同進程間的組件bind(粘連)在一起,實現通信。
為什麼android選用Binder來實現進程間通信?
一、可靠性。在移動設備上,通常采用基於Client-Server的通信方式來實現互聯網與設備間的內部通信。目前linux支持IPC包括傳統的管道,System V IPC,即消息隊列/共享內存/信號量,以及socket中只有socket支持Client-Server的通信方式。Android系統為開發者提供了豐富進程間通信的功能接口,媒體播放,傳感器,無線傳輸。這些功能都由不同的server來管理。開發都只關心將自己應用程序的client與server的通信建立起來便可以使用這個服務。毫無疑問,如若在底層架設一套協議來實現Client-Server通信,增加了系統的復雜性。在資源有限的手機 上來實現這種復雜的環境,可靠性難以保證。
二、傳輸性能。socket主要用於跨網絡的進程間通信和本機上進程間的通信,但傳輸效率低,開銷大。消息隊列和管道采用存儲-轉發方式,即數據先從發送方緩存區拷貝到內核開辟的一塊緩存區中,然後從內核緩存區拷貝到接收方緩存區,其過程至少有兩次拷貝。雖然共享內存無需拷貝,但控制復雜。比較各種IPC方式的數據拷貝次數。共享內存:0次。Binder:1次。Socket/管道/消息隊列:2次。
三、安全性。Android是一個開放式的平台,所以確保應用程序安全是很重要的。Android對每一個安裝應用都分配了UID/PID,其中進程的UID是可用來鑒別進程身份。傳統的只能由用戶在數據包裡填寫UID/PID,這樣不可靠,容易被惡意程序利用。而我們要求由內核來添加可靠的UID。
所以,出於可靠性、傳輸性、安全性。android建立了一套新的進程間通信方式。
到了這裡,我們對於Binder有了一些簡要的理解。
後面我們會繼續深入討論Bind機制:
1.Binder的服務端是如何設計的?
2.Binder的客戶端是如何設計的?
3.Binder對象是如何被獲取到的?