在Android系統中,涉及到多線程間的通訊,底層都是依賴於Binder IPC機制。例如當進程A中的Activity要想進程吧B中的Service通訊,這便須要依賴於Binder IPC。不只於此,整個Android系統架構中,大量採用Binder機制來做爲IPC(進程間通訊,Interprocess Communication)方案。android
固然也存在部分其餘的IPC方式,如管道、SystemV、Socket等。那麼Android爲何不使用這個原有技術,而是要開發一種新的Binder的進程間通訊機制呢?git
在移動設備上(性能受限制的設備,好比要省電),普遍地使用跨進程通訊對通訊機制的性能有嚴格的要求,Binder相對於傳統的Socket方式,更加高效。github
Binder數據拷貝只須要一次,而管道、消息隊列、Socket都須要兩次,共享內存方式一次內存拷貝都不要,但實現方式又比較複雜。安全
傳統的進程通訊方式對於通訊雙方的身份並無作出嚴格的驗證,好比Socket通訊的IP地址是客戶端手動填入,很容易進行僞造。然而,Binder機制從協議自己就支持對通訊雙方作身份驗校驗,從而大大提高了安全性。bash
從進場角度來看IPC(Interprocess Communication)機制(圖片來源)多線程
每一個Android的進程,只能運行在本身進程所擁有的虛擬地址空間。架構
如,對應一個4GB的虛擬地址空間,其中3GB是用戶空間,1GB是內核空間。內核空間大小能夠經過參數調整,而用戶空間進程私有,沒法共享,但內核空間是可共享的。佈局
Client進程向Service進程通訊,偏偏是利用進程間可共享的內核內存空間來完成底層通訊工做的。性能
Client端和Service端進程每每採用ioctl等方式與內核空間驅動進行交互。spa
Binder通訊採用C/S架構,從組件視角來講,包含Client、Service、ServiceManager以及Binder驅動,其中ServiceManager用於管理系統中的各類服務。架構圖以下:(圖片來源)
Binder通訊的四個角色
Client進程:使用服務的進程
Service進程:提供服務的進程
ServiceManager進程:ServiceManger的做用是將字符形式的Binder名字轉化成Client中對該Binder的引用,使得Client可以經過Binder名字得到對Service中Binder實體的引用。
Binder驅動:驅動負責進程間Binder通訊的創建,Binder在進程之間的傳遞,Binder引用計數管理,數據包在進程之間的傳遞和交互等一系列底層支持。
圖中Client/Service/ServiceManager之間的相互通訊都是基於Binder機制。既然基於Binder機制通訊,那麼一樣也是C/S架構,雜圖中的3大步驟都對應的Client端與Service端。
Service進程要先註冊Service到ServiceManager。這個過程:Service是客戶端,而ServiceManager是服務端
Client進程使用某個Service以前,須先向ServiceManager中獲取相應的Service。該過程:Client是客戶端,Service是服務端
Client根據獲得的Service信息創建與Service所在的Service進程通訊的道路,而後就能夠直接與Service交互。該過程:Client是客戶端,Service是服務端。
圖中的Client、Service、ServiceManager之間交互都是虛線表示,是因爲它們彼此直接不是直接交互的,而是都經過與Binder驅動進行交互的,從而實現IPC通訊方式。
其中,Binder驅動位於內核空間,Client、Service、ServiceManager位於用戶空間。
Binder驅動和ServiceManager能夠看作是Android平臺的基礎架構,而Client和Service是Android的應用層,開發人員只需自定義實現Client、Service端,藉助Android的基礎平臺架構即可以直接進行IPC通訊。
首先咱們看看咱們的程序跨進程調用系統服務的簡單示例,實現浮動窗口的部分代碼:
//獲取WindowManager服務引用
WindowManager wm = (WindowManager) getSystemService(getApplication().WINDOW_SERVICE);
//佈局參數layoutParams相關設置略...
View view = LayoutInflater.from(getApplication()).inflate(R.layout.float_layout, null);
//添加view
wm.addView(view, layoutParams);複製代碼
Service
,並將這些Service
向ServiceManager
註冊(即讓ServiceManager管理)。這一步是系統自動完成的。ServiceManager
查詢獲得具體的Service
引用,一般是Service
引用的代理對象,對數據進行一些處理操做。即第2行代碼中,獲得的wm是WindowManger對象的引用。WindowManager
的addView
方法,將觸發遠程調用,調用的是運行在systemService
進程中的WindowManager的addView
方法。Parcel
發送給內核中的Binder Driver
Service
會讀取Binder Driver
中的請求數據,若是是發送給本身的,解包Parcel對象,處理並將結果返回Client調用過程
不該在主線程。