Binder原理

1、概述

在Android系統中,涉及到多線程間的通訊,底層都是依賴於Binder IPC機制。例如當進程A中的Activity要想進程吧B中的Service通訊,這便須要依賴於Binder IPC。不只於此,整個Android系統架構中,大量採用Binder機制來做爲IPC(進程間通訊,Interprocess Communication)方案。android

固然也存在部分其餘的IPC方式,如管道、SystemV、Socket等。那麼Android爲何不使用這個原有技術,而是要開發一種新的Binder的進程間通訊機制呢?git


一、爲何要使用Binder

  • 性能方面

在移動設備上(性能受限制的設備,好比要省電),普遍地使用跨進程通訊對通訊機制的性能有嚴格的要求,Binder相對於傳統的Socket方式,更加高效。github

Binder數據拷貝只須要一次,而管道、消息隊列、Socket都須要兩次共享內存方式一次內存拷貝都不要,但實現方式又比較複雜安全

  • 安全方面

傳統的進程通訊方式對於通訊雙方的身份並無作出嚴格的驗證,好比Socket通訊的IP地址是客戶端手動填入,很容易進行僞造。然而,Binder機制協議自己就支持對通訊雙方作身份驗校驗,從而大大提高了安全性。bash


2、Binder原理

一、IPC原理

從進場角度來看IPC(Interprocess Communication)機制(圖片來源多線程


每一個Android的進程,只能運行在本身進程所擁有的虛擬地址空間。架構

如,對應一個4GB的虛擬地址空間,其中3GB是用戶空間,1GB是內核空間。內核空間大小能夠經過參數調整,而用戶空間進程私有,沒法共享,但內核空間是可共享的佈局

Client進程向Service進程通訊,偏偏是利用進程間可共享的內核內存空間來完成底層通訊工做的。性能

Client端和Service端進程每每採用ioctl等方式內核空間驅動進行交互spa


二、Binder原理

Binder通訊採用C/S架構,從組件視角來講,包含Client、Service、ServiceManager以及Binder驅動,其中ServiceManager用於管理系統中的各類服務。架構圖以下:(圖片來源


Binder通訊的四個角色

Client進程:使用服務的進程

Service進程:提供服務的進程

ServiceManager進程:ServiceManger的做用是將字符形式的Binder名字轉化成Client中對該Binder的引用,使得Client可以經過Binder名字得到對Service中Binder實體的引用。

Binder驅動:驅動負責進程間Binder通訊的創建,Binder在進程之間的傳遞,Binder引用計數管理,數據包在進程之間的傳遞和交互等一系列底層支持。


三、Binder運行機制

圖中Client/Service/ServiceManager之間的相互通訊都是基於Binder機制。既然基於Binder機制通訊,那麼一樣也是C/S架構,雜圖中的3大步驟都對應的Client端與Service端。

  • 註冊服務(addService)

Service進程要先註冊Service到ServiceManager。這個過程:Service是客戶端,而ServiceManager是服務端

  • 獲取服務(getService)

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通訊


四、Binder運行的實例解釋

首先咱們看看咱們的程序跨進程調用系統服務的簡單示例,實現浮動窗口的部分代碼:

//獲取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);複製代碼

  • 註冊服務(addService):在Android開啓啓動過程中,Android會初始化系統的各類Service,並將這些ServiceServiceManager註冊(即讓ServiceManager管理)。這一步是系統自動完成的
  • 得到服務(getService):客戶端想要獲得具體的Service,直接向ServiceManager要便可。客戶端首先向ServiceManager查詢獲得具體的Service引用,一般是Service引用的代理對象,對數據進行一些處理操做。即第2行代碼中,獲得的wm是WindowManger對象的引用。
  • 使用服務:經過這個引用向具體的服務端發送請求,服務端執行完成後就返回。即第6行調用WindowManageraddView方法,將觸發遠程調用,調用的是運行在systemService進程中的WindowManager的addView方法。


五、使用服務的具體執行過程


  1. Client經過得到一個Service的代理接口,對Service進行調用
  2. 代理接口中定義的方法Service中定義的方法一一對應
  3. Client調用某個代理接口中的方法時,代理接口的方法會將Client傳遞的參數打包成Parcel對象
  4. 代理接口將Parcel發送給內核中的Binder Driver
  5. Service讀取Binder Driver中的請求數據,若是是發送給本身的,解包Parcel對象,處理並將結果返回
  6. 整個的調用過程是一個同步過程,在Service處理的時候,Client會Block住,所以Client調用過程不該在主線程
相關文章
相關標籤/搜索