天天看點

Android之Binder機制

1. 簡介

Binder,中文即粘合劑,意思是粘合了兩個不同的程序。從IPC角度來說,Binder是Android中的一種跨程序通信方式。

2. 基礎概念介紹

2.1 程序隔離&跨程序通信

  • 程序隔離:為了保證安全性和獨立性,一般情況下,一個程序不能直接操作或通路另外一個程序。即Android中的程序是互相隔離,獨立的
  • 程序通信:即IPC,不同程序需要進行資料的互動和通信

2.2 核心空間&使用者空間

  • 一個程序空間分為核心空間和使用者空間,即核心空間和使用者空間相隔離
  • 核心空間:即Karnel Space,是Linux核心的運作空間。可以執行任何指令, 調用系統的一切資源。與使用者空間隔離,即使使用者的程式崩潰了,核心也不會受到影響。核心空間可進行程序間,程序内的互動。核心空間的資料是共享的,故核心空間=可共享空間
  • 使用者空間:即User Space,是使用者程式的運作空間。隻能進行簡單的操作,在使用者空間的程序不能直接互動,可以通過核心空間來進行間接互動,但是又不能直接調用系統的資源,必須通過系統接口(System Call),向核心發出指令。使用者空間的資料不共享,給使用者空間=不可共享空間

2.3 記憶體映射

  • 定義:關聯一個虛拟記憶體區域和一個磁盤上的共享對象,使兩者存在映射關系
  • 實作過程:通過Linux系統調用函數:mmap(),這個函數的作用就是建立虛拟記憶體區域,并與共享對象建立映射關系
  • 特點:減少了資料拷貝的次數,并通過映射區域實作使用者空間和核心空間的互動
傳統跨程序通信需要拷貝資料兩次,Binder機制隻需要1次,主要是因為Binder機制使用到了記憶體映射

3. 四大角色

  • Client:使用服務的程序
  • Server:提供服務的程序
  • ServiceManager:管理系統的Server的注冊和查詢(将字元形式的Binder名字轉化成Client對該Binder的引用)
  • Binder驅動:虛拟裝置驅動,連接配接Client,Server,ServiceManager的橋梁

3.1 Binder驅動

Binder驅動是Binder通信的核心,它工作于核心空間,提供open,mmap,ioctl等标準檔案操作。驅動負責程序間Binder通信的建立。分别管理着Server端的Binder實體核Client端的引用。

4. Binder架構

  • Binder通信采用C/S模式,包括四個元件:Client,Server,ServiceManager,Binder驅動。其中Client,Server,ServiceManager運作在使用者空間,Binder驅動運作在核心空間。
  • Binder在Framework層進行封裝,通過JNI技術調用Native層的Binder架構
  • 在Native層的Binder以ioctl,open等操作與Binder驅動通訊。

5. Binder原理及步驟

Android之Binder機制

5.1 注冊服務

  • Server建立Binder實體,取一個可讀易記的名字,将Binder實體連同名字以資料包的形式通過Binder驅動發送給ServiceManager,通知ServiceManger注冊這個Binder實體。在這裡Server需要通過0号引用與ServiceManager的Binder進行通訊
  • Binder驅動為這個穿越邊界的Binder實體在核心空間建立節點和ServiceManager的引用,并将名字和引用打包傳遞給ServiceManager
  • ServiceManager收到資料包後,從中取出名字和引用填入查找表中

5.2 擷取服務

  • Client利用保留的0号引用向ServiceManager請求通路某個Binder
  • ServiceManager根據請求的資料包擷取Binder名字,在查找表中找到該名字對應的Binder引用
  • 将該引用作為回複傳回給發起請求的Client

5.2 使用服務

  • Client将程序參數發送到Server程序
  • Binder驅動為跨程序通信做準備,實作記憶體映射
  • Server根據Client的參數,執行目标方法
  • Server程序将目标方法的結果傳回給Client程序

6. Binder機制的優點

6.1 高效

消息隊列和管道采用的是存儲-轉發方式,至少需要兩次資料拷貝過程,效率比較低。共享記憶體雖然無需拷貝,但控制複雜,難以使用。而Binder由于使用了記憶體映射,隻需進行一次資料拷貝,效率高

6.2 安全性高

Binder機制為每個程序配置設定了UID/PID來鑒别身份的辨別,并且在Binder通信時會根據UID/PID進行有效性檢測

6.3 使用簡單,可操作性高

Binder機制采用Client/Server的通信方式,對于管道,共享記憶體,消息隊列以及Socket來說隻有Socket采用了Client/Server的通信方式,但是Socket主要用于跨網絡的程序通信,開銷大,效率低。另外Binder機制還實作了面向對象的調用方式。

7. Android中的IPC方式

7.1 Bundle

兩個使用場景:一是直接利用傳遞資料,在Bundle中附加資訊,通過Intent發送出去。二是轉移目标跨程序通信,将需要在A程序計算的任務轉移到B程序的背景Service中執行。

7.2 檔案共享

兩個程序通過讀/寫同一個檔案實作交換資料。在這裡需注意的是SharePreferences,它的底層是使用Xml檔案來存儲鍵值對,當使用SharePreferences時,記憶體中會有一份緩存,故在多程序讀寫時,就會出現資料過期的狀況,另外在高并發讀取時,很大幾率會出現資料丢失,故不建議在程序通信使用Share Preferences

7.4 Messenger

輕量級IPC,其底層的實作其實是AIDL。首先來看看其工作原理圖

Android之Binder機制

根據工作原理圖來分析其實作過程:

服務程序

  1. 建立一個Service來處理用戶端的連接配接請求
  2. Service中建立一個Handler來接受用戶端發送過來的消息,并通過這個Handler來建立一個Messenger對象,在onBind中傳回Messenger對象的底層binder

客戶程序

  1. 首先綁定Service,綁定成功後利用Service傳回的Binder對象建立一個Messenger對象
  2. 通過這個Messenger對象向服務端發送消息,消息類型為Message

服務程序回複客戶程序

  1. 當服務程序收到客戶程序的消息後,進行回複時,則用戶端需在上面的基礎上建立一個Handler來接受服務端的回複資訊,并利用這個Handler對象建立Messenger對象,并把這個對象通過message的reply參數在發送資訊時傳遞給服務端。
  2. 服務端在接受到用戶端的資訊時,利用攜帶的reply參數得到Messenger對象,然後利用這個對象就可以向用戶端發送message消息類型的消息。

7.5 AIDL

大緻流程

首先建立一個Service和AIDL接口,接着建立一個類并繼承AIDL接口中Stub,重寫Stub的抽象方法,在Service中的onBind傳回這個類的對象,然後用戶端綁定服務端的Service,綁定成功後将傳回的Binder對象轉化成AIDL接口所屬的類型,然後就可以調用接口中的方法。

難點

  1. 支援的資料類型
  • 基本資料類型
  • String和CharSequence
  • List:隻支援ArrayList,裡面的元素必須能夠被AIDL支援
  • map:隻支援HashMap,鍵值都必須能夠被AIDL支援
  • Parcelable
  • AIDL
  1. AIDL檔案中使用到自定義的Parcelable對象都要建立一個和它同名的AIDL檔案,隻要在檔案中聲明那個類為Parcelable即可
  2. 自定義的Parcelable對象和AIDL對象必須都要顯示import進來
  3. 除基本類型外,其他類型需标上方向,in、out、inout
  4. AIDL接口隻支援方法,不支援聲明靜态常量

7.6 ContentProvider

ContentProvider是Android中提供的專門用于不同應用間進行資料共享的方式,故它天生就适合程序間的通訊,和Messenger一樣,它的底層實作也是Binder

7.7 Socket

又稱套接字,網絡通信中的概念。主要分為流式套接字(TCP)和使用者資料報套接字(UDP)

7.8 Android中各種IPC方式的優缺點

名稱 優點 缺點 适用場景
Bundle 簡單易用 隻能傳輸Bundle支援的資料類型 四大元件的程序間的通信
檔案共享 簡單易用 不适合高并發場景,無法做到即時通信 無并發通路情況,交換簡單的資料實時性不高的場景
AIDL 功能強大,支援一對多并發通信,支援實時通信 操作較複雜,需處理好線程同步 一對多通信,有RPC需求
Messenger 支援一對多的串行通信,支援實時通信 不能很好處理高并發情形,不支援RPC,資料通過Message傳遞,故隻能傳輸Bundle支援的資料類型 低并發的一對多及時需求,無RPC需求,或者無傳回結果的RPC需求
ContentProvider 資料通路功能強大,支援一對多并發資料共享 受限制的AIDL 一對多的程序間的資料共享
Socket 功能強大,可以通過網絡傳遞位元組流,支援一對多實時通信 實作細節繁瑣,不支援直接的RPC 網絡資料交換

參考資料

圖文詳解 Android Binder跨程序通信的原理

作業系統:圖文詳解 記憶體映射

Android Bander設計與實作

一篇文章了解相見恨晚的 Android Binder 程序間通訊機制

《Android開發藝術探索》

繼續閱讀