前言
- 如果你接觸過 跨進程通信 (
IPC
),那麼你對Binder
一定不陌生 - 雖然 網上有很多介紹
Binder
的文章,可是存在一些問題:淺顯的討論Binder
機制 或 一味講解Binder
源碼、邏輯不清楚,最終導致的是讀者們還是無法形成一個完整的Binder
概念 - 本文采用 清晰的圖文講解方式,按照 大角度 -> 小角度 去分析
Binder
,即:- 先從 機制、模型的角度 去分析 整個
Binder
跨進程通信機制的模型 - 再 從源碼實現角度,分析
Binder
在Android
中的具體實現
- 先從 機制、模型的角度 去分析 整個
從而全方位地介紹 Binder
,希望你們會喜歡。
目錄
- Binder到底是什麼?
- 中文即 粘合劑,意思爲粘合了兩個不同的進程
- 網上有很多對
Binder
的定義,但都說不清楚:Binder
是跨進程通信方式、它實現了IBinder
接口,是連接ServiceManager
的橋樑blabla,估計大家都看暈了,沒法很好的理解 - 我認爲:對於
Binder
的定義,在不同場景下其定義不同
在本文的講解中,按照 大角度 -> 小角度 去分析Binder
,即:
- 先從 機制、模型的角度 去分析 整個
Binder
跨進程通信機制的模型 其中,會詳細分析模型組成中的Binder
驅動 - 再 從源碼實現角度,分析
Binder
在Android
中的具體實現
從而全方位地介紹 Binder
,希望你們會喜歡。
2. 知識儲備
在講解Binder
前,我們先了解一些基礎知識
2.1 進程空間分配
- 一個進程空間分爲 用戶空間 & 內核空間(
Kernel
),即把進程內 用戶 & 內核 隔離開來 - 二者區別:
- 進程間,用戶空間的數據不可共享,所以用戶空間 = 不可共享空間
- 進程間,內核空間的數據可共享,所以內核空間 = 可共享空間
- 進程內 用戶 與 內核 進行交互 稱爲系統調用
2.2 進程隔離
爲了保證 安全性 & 獨立性,一個進程 不能直接操作或者訪問另一個進程,即Android
的進程是相互獨立、隔離的
2.3 跨進程通信( IPC
)
- 隔離後,由於某些需求,進程間 需要合作 / 交互
- 跨進程間通信的原理
- 先通過 進程間 的內核空間進行 數據交互
- 再通過 進程內 的用戶空間 & 內核空間進行 數據交互,從而實現 進程間的用戶空間 的數據交互
而Binder
,就是充當 連接 兩個進程(內核空間)的通道。
3. Binder 跨進程通信機制 模型
3.1 模型原理
Binder
跨進程通信機制 模型 基於 Client - Server
模式,模型原理圖如下:
相信我,一張圖就能解決問題
3.2 額外說明
說明1:Client
進程、Server
進程 & Service Manager
進程之間的交互都必須通過Binder
驅動(使用 open
和 ioctl
文件操作函數),而非直接交互 **
原因:
Client
進程、Server
進程 &Service Manager
進程屬於進程空間的用戶空間,不可進行進程間交互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相加) 即:Client
進程 需要傳兩個整數給Server
進程Server
進程 需要把相加後的結果 返回給Client
進程
- 具體步驟
下面,我會根據
Binder
跨進程通信機制 模型的步驟進行分析
步驟1:註冊服務
- 過程描述
Server
進程 通過Binder
驅動 向Service Manager
進程 註冊服務 - 代碼實現
Server
進程 創建 一個Binder
對象Binder
實體是Server
進程 在Binder
驅動中的存在形式- 該對象保存
Server
和ServiceManager
的信息(保存在內核空間中) Binder
驅動通過 內核空間的Binder
實體 找到用戶空間的Server
對象
註冊服務後,Binder
驅動持有 Server
進程創建的Binder
實體
步驟2:獲取服務
Client
進程 使用 某個service
前(此處是 相加函數),須 通過Binder
驅動 向ServiceManager
進程 獲取相應的Service
信息- 具體代碼實現過程如下:
此時,Client
進程與 Server
進程已經建立了連接
步驟3:使用服務
Client
進程 根據獲取到的 Service
信息(Binder
代理對象),通過Binder
驅動 建立與 該Service
所在Server
進程通信的鏈路,並開始使用服務
- 過程描述
Client
進程 將參數(整數a和b)發送到Server
進程Server
進程 根據Client
進程要求調用 目標方法(即加法函數)Server
進程 將目標方法的結果(即加法後的結果)返回給Client
進程
- 代碼實現過程
步驟1: Client
進程 將參數(整數a和b)發送到Server
進程
步驟2:Server
進程根據Client
進要求 調用 目標方法(即加法函數)
步驟3:Server
進程 將目標方法的結果(即加法後的結果)返回給Client
進程
- 總結 下面,我用一個原理圖 & 流程圖來總結步驟3的內容
原理圖
5. 優點
對比 Linux
(Android
基於Linux
)上的其他進程通信方式(管道/消息隊列/共享內存/信號量/Socket),Binder
機制的優點有:
- 高效
Binder
數據拷貝只需要一次,而管道、消息隊列、Socket
都需要2次- 通過驅動在內核空間拷貝數據,不需要額外的同步處理
- 安全性高
Binder
機制爲每個進程分配了UID/PID
來作爲鑑別身份的標示,並且在Binder
通信時會根據UID/PID
進行有效性檢測- 傳統的進程通信方式對於通信雙方的身份並沒有做出嚴格的驗證
- 如,
Socket
通信ip
地址是客戶端手動填入,容易出現僞造
- 使用簡單
- 採用
Client/Server
架構 - 實現 面向對象 的調用方式,即在使用
Binder
時就和調用一個本地對象實例一樣
- 採用
6. 總結
- 本文主要詳細講解 跨進程通信模型
Binder
機制 ,總結如下:
定義