Android Binder跨進程通信


前言

  • 如果你接觸過 跨進程通信 (IPC),那麼你對Binder一定不陌生
  • 雖然 網上有很多介紹 Binder的文章,可是存在一些問題:淺顯的討論Binder機制 或 一味講解 Binder源碼、邏輯不清楚,最終導致的是讀者們還是無法形成一個完整的Binder概念
  • 本文采用 清晰的圖文講解方式,按照 大角度 -> 小角度 去分析Binder,即:
    1. 先從 機制、模型的角度 去分析 整個Binder跨進程通信機制的模型
    2. 再 從源碼實現角度,分析 BinderAndroid中的具體實現

從而全方位地介紹 Binder,希望你們會喜歡。


目錄


  1. Binder到底是什麼?
  • 中文即 粘合劑,意思爲粘合了兩個不同的進程
  • 網上有很多對Binder的定義,但都說不清楚:Binder是跨進程通信方式、它實現了IBinder接口,是連接 ServiceManager的橋樑blabla,估計大家都看暈了,沒法很好的理解
  • 我認爲:對於Binder的定義,在不同場景下其定義不同

在本文的講解中,按照 大角度 -> 小角度 去分析Binder,即:

  • 先從 機制、模型的角度 去分析 整個Binder跨進程通信機制的模型 其中,會詳細分析模型組成中的 Binder驅動
  • 再 從源碼實現角度,分析 BinderAndroid中的具體實現

從而全方位地介紹 Binder,希望你們會喜歡。


2. 知識儲備

在講解Binder前,我們先了解一些基礎知識

2.1 進程空間分配

  • 一個進程空間分爲 用戶空間 & 內核空間(Kernel),即把進程內 用戶 & 內核 隔離開來
  • 二者區別:
    1. 進程間,用戶空間的數據不可共享,所以用戶空間 = 不可共享空間
    2. 進程間,內核空間的數據可共享,所以內核空間 = 可共享空間
  • 進程內 用戶 與 內核 進行交互 稱爲系統調用

2.2 進程隔離

爲了保證 安全性 & 獨立性,一個進程 不能直接操作或者訪問另一個進程,即Android的進程是相互獨立、隔離的

2.3 跨進程通信( IPC

  • 隔離後,由於某些需求,進程間 需要合作 / 交互
  • 跨進程間通信的原理
    1. 先通過 進程間 的內核空間進行 數據交互
    2. 再通過 進程內 的用戶空間 & 內核空間進行 數據交互,從而實現 進程間的用戶空間 的數據交互

Binder,就是充當 連接 兩個進程(內核空間)的通道。


3. Binder 跨進程通信機制 模型

3.1 模型原理

Binder 跨進程通信機制 模型 基於 Client - Server 模式,模型原理圖如下:

相信我,一張圖就能解決問題

3.2 額外說明

說明1:Client進程、Server進程 & Service Manager 進程之間的交互都必須通過Binder驅動(使用 openioctl文件操作函數),而非直接交互 **

原因:

  1. Client進程、Server進程 & Service Manager進程屬於進程空間的用戶空間,不可進行進程間交互
  2. Binder驅動 屬於 進程空間的 內核空間,可進行進程間 & 進程內交互

所以,原理圖可表示爲以下:

虛線表示並非直接交互

說明2:
Binder驅動 & Service Manager進程 屬於 Android基礎架構(即系統已經實現好了);而Client 進程 和 Server 進程 屬於Android應用層(需要開發者自己實現)

所以,在進行跨進程通信時,開發者只需自定義Client & Server 進程 並 顯式使用上述3個步驟,最終藉助 Android的基本架構功能就可完成進程間通信

說明3:Binder請求的線程管理
  • Server進程會創建很多線程來處理Binder請求
  • 管理Binder模型的線程是採用Binder驅動的線程池,並由Binder驅動自身進行管理 而不是由Server進程來管理的
  • 一個進程的Binder線程數默認最大是16,超過的請求會被阻塞等待空閒的Binder線程。 所以,在進程間通信時處理併發問題時,如使用ContentProvider時,它的CRUD(創建、檢索、更新和刪除)方法只能同時有16個線程同時工作
  • 至此,我相信大家對Binder 跨進程通信機制 模型 已經有了一個非常清晰的定性認識
  • 下面,我將通過一個實例,分析Binder跨進程通信機制 模型在 Android中的具體代碼實現方式 即分析 上述步驟在Android中具體是用代碼如何實現的

4. Binder機制 在Android中的具體實現原理

  • Binder機制在 Android中的實現主要依靠 Binder類,其實現了IBinder 接口 下面會詳細說明
  • 實例說明:Client進程 需要調用 Server進程的加法函數(將整數a和b相加) 即:
    1. Client進程 需要傳兩個整數給 Server進程
    2. Server進程 需要把相加後的結果 返回給Client進程
  • 具體步驟 下面,我會根據Binder 跨進程通信機制 模型的步驟進行分析

步驟1:註冊服務

  • 過程描述 Server進程 通過Binder驅動 向 Service Manager進程 註冊服務
  • 代碼實現 Server進程 創建 一個 Binder 對象
    1. Binder 實體是 Server進程 在 Binder 驅動中的存在形式
    2. 該對象保存 ServerServiceManager 的信息(保存在內核空間中)
    3. Binder 驅動通過 內核空間的Binder 實體 找到用戶空間的Server對象

註冊服務後,Binder驅動持有 Server進程創建的Binder實體

步驟2:獲取服務

  • Client進程 使用 某個 service前(此處是 相加函數),須 通過Binder驅動 向 ServiceManager進程 獲取相應的Service信息
  • 具體代碼實現過程如下:

此時,Client進程與 Server進程已經建立了連接

步驟3:使用服務

Client進程 根據獲取到的 Service信息(Binder代理對象),通過Binder驅動 建立與 該Service所在Server進程通信的鏈路,並開始使用服務

  • 過程描述
    1. Client進程 將參數(整數a和b)發送到Server進程
    2. Server進程 根據Client進程要求調用 目標方法(即加法函數)
    3. Server進程 將目標方法的結果(即加法後的結果)返回給Client進程
  • 代碼實現過程

步驟1: Client進程 將參數(整數a和b)發送到Server進程

步驟2:Server進程根據Client進要求 調用 目標方法(即加法函數)

步驟3:Server進程 將目標方法的結果(即加法後的結果)返回給Client進程

  • 總結 下面,我用一個原理圖 & 流程圖來總結步驟3的內容

原理圖


5. 優點

對比 LinuxAndroid基於Linux)上的其他進程通信方式(管道/消息隊列/共享內存/信號量/Socket),Binder 機制的優點有:

  • 高效
    1. Binder數據拷貝只需要一次,而管道、消息隊列、Socket都需要2次
    2. 通過驅動在內核空間拷貝數據,不需要額外的同步處理
  • 安全性高 Binder 機制爲每個進程分配了 UID/PID 來作爲鑑別身份的標示,並且在 Binder 通信時會根據 UID/PID 進行有效性檢測
    1. 傳統的進程通信方式對於通信雙方的身份並沒有做出嚴格的驗證
    2. 如,Socket通信 ip地址是客戶端手動填入,容易出現僞造
  • 使用簡單
    1. 採用Client/Server 架構
    2. 實現 面向對象 的調用方式,即在使用Binder時就和調用一個本地對象實例一樣

6. 總結

  • 本文主要詳細講解 跨進程通信模型 Binder機制 ,總結如下:

定義

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章