Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android IPC Binder

Android IPC Binder

編輯:關於Android編程

(一)前言

Binder原本是IPC工具,但是在Android中它的主要作用是支持RPC(Remote Procedure Call),使得當前進程調用另一個進程的函數就像調用自身的函數是一樣輕松簡單。Binder又Service Server(含有Android的服務)、Service Client(使用服務的客戶端)、Context Manager(確定服務的位置)、以及Binder Dirver四大部分組成。

Anroid是基於Linux內核的操作平台,Android進程和Linux進程一樣,它們只運行在進程固有的虛擬地址空間中。用戶代碼與相關庫運行在用戶空間內,而內核空間中運行的代碼則運行在內核空間中的各個區域中。並且,進程具有獨立的地址空間,單獨運行。但是內核空間是被其他用戶進程所共享的。那麼兩個進程是如何相互通信的呢?顯然是要經過兩個進程共享的內核空間了。從內核的角度看,進程只不過是一個作業單位,雖然那各進程的用戶空間相互獨立,但運行在內核空間中的任務數據、代碼都是批次共享的。
內核與用戶空間


(二)使用Binder的原因

Binder采用Linux中優秀的內存管理技術,在通過內核空間傳遞數據時能確保數據的可靠性 由於使用用戶空間無法訪問的內核空間來交換數據,IPC間的安全問題得到解決

(三)Android Binder Model

服務客戶端要通過Binder IPC實現對Service Serverf的foo()函數的調用,Binder Dirver充當中間人的角色,將從服務客戶端接收到的Binder IPC數據傳遞給Service Server。具體過程如圖:
這裡寫圖片描述
Binder IPC數據包含調用其他進程函數的信息,是Binder Dirver操作的IPC數據單位。

IPC數據包含函數調用相關的內容,她由待調服務號、待調函數名、Binder協議構成。在Android中服務號用來標記運行中的各個服務,便於區分不同的服務;待調函數名用來指定服務客戶端將調用的服務中的函數;Binder 協議是處理進程間IPC數據的約定。如圖:
Binder IPC數據
Handler指服務號,用來區分不同服務。RPC代碼與RPC數據分別表示的是待調函數與傳遞的參數,即RPC代碼確定數據要傳遞給服務中的哪個函數,RPC數據是傳遞給RPC代碼所指定函數的參數。Binder協議表示IPC數據的處理辦法。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxociAvPg0KPGgyIGlkPQ=="四binder-ipc數據傳遞">(四)Binder IPC數據傳遞

Binder Dirver是字符驅動設備,通過調用open()或者ioct1()函數即可訪問。如下圖,顯示了系統調用與Binder Dirver中文件運算符函數之間的連接關系。例如:系統調用open()函數與Binder Dirver的binder_open函數連接在一起。
Binder系統調用
應用程序在通過Binder嘗試RPC操作時,會進行open()系統調用,獲取Binder Dirver的文件描述符。而後,通過mmap()系統調用,在內核中開辟一塊區域,以便存放IPC數據。最後,調用ioct1()函數,將IPC數據作為參數傳遞給Binder Dirver。


(五)Binder IPC數據流

服務客戶端調用Service Server的服務函數的過程。如下圖所示:
Binder IPC抽象層

服務層:該層包含一系列提供特定功能的服務函數。服務客戶端虛擬調用指定的函數,而實際上調用是由Service Server進行的。 PRC層:服務客戶端在該層生成用於調用服務函數的RPC代碼和RPC數據。Service Server會根據傳遞過來的RPC代碼查找相應的函數,並將RPC數據傳遞給查找到的函數。 IPC層:該層將RPC層生成的RPC代碼和RPC數據封裝成為Binder IPC數據,以便將它們傳遞給Binder Dirver。 Binder Dirver層:接收來自IPC層的Binder IPC數據,查找包含指定服務的Service Server,並將IPC數據傳遞給查找到的Service Server。

(六)Binder 協議

Binder協議包含在BinderIPC數據中,它從IPC層傳遞到Binder Dirver,或者從Binder Dirver傳遞到IPC層。根據傳遞方向,Binder協議分為兩種,一種是從IPC層傳遞到Binder Dirver層的“BINDER COMMAND PROTOCAL”,另一種是從Binder Dirver層傳遞到IPC層的“BINDER RETURN PROTOCAL”。兩種協議的區別在於”BINDER COMMAND PROTOCAL”是以BC_打頭的,而“BINDER RETURN PROTOCAL”是以BR_打頭的。
Binder協議的分類
Binder協議

首先,服務客戶端使用BC_TRANSACTION將Binder IPC數據傳遞給Binder Dirver。Binder Dirver接收IPC數據後,分析其中使用的協議,若是BC_TRANSACTION,則根據IPC數據中的Handler信息查找相應的Service Server。然後Binder Dirver會將協議更改為BR_TRANSACTION協議,並將其插入到IPC數據中,把包含BR_TRANSACTION協議的IPC數據傳遞到Service Server中。Service Server接收到來自Binder Dirver的IPC數據後,分析其中的協議,若是BR_TRANSACTION,則進一步分析IPC數據,調用服務客戶端請求的函數。函數執行完成後會按照逆向過程的將IPC應答數據發送給服務客戶端。如圖:
Binder協議不同處理


(七)Binder尋址

在Android系統中,有一個Context Manager的特殊進程,它為每個服務分配一個稱為Handler的編號,並提供服務的注冊、檢索等管理功能【Context Manager自身的Handler值被設置為0】。如前所述,Binder Dirver會根據IPC數據中的Handler查找Service Server。為了順利實現Binder尋址,Service Server必須先把自身服務【傳送IPC數據,其中包含RPC代碼、RPC數據,並且Handler值設置為0】的訪問信息注冊到Context Manager。
7.1 服務注冊
當Service Server向Context Manager注冊自身服務時,Binder Dirver就會進行Binder尋址。Binder Dirver首先查找Handler值為0的Binder結點,Handler值為0的Binder結點是Context Manager,Service Server會將IPC數據傳遞給Context Manager。然後Binder Dirver會生成一個Binder結點,用來表示Service Server中的服務A,接下來生成Binder結點引用數據,以便Context Manager識別所生成的Binder結點,並將相關結點連接起來。根據生成的順序引用數據會被編號,這種編號將插入到IPC數據中,傳遞給Context Manager。Context Manager會根據IPC數據中的服務名稱與Binder結點編號,將服務注冊到自身的服務目錄列表中。如圖:
服務注冊

7.2 服務檢索
當服務注冊在Android啟動階段完成後,Context Manager的服務列表、Binder Dirver的Binder結點,以及Service Server中的服務就連接在一起了,注冊在Context Manager中的服務就可以被其他進程使用了。服務檢索過程描述的是服務客戶端在檢索服務時進行Binder尋址的整個過程。首先,服務客戶端會將包含RPC代碼、RPC數據、值為0的Handler的IPC數據經由Binder Dirver傳遞至Context Manager中。Context Manager接收到IPC數據後,根據IPC數據中包含的所請求的服務名稱,在自身持有的服務列表中查找對應的服務編號,將查找到的服務編號發送給Binder Dirver。Binder Dirver將根據傳遞過來的服務編號查找對應的引用數據,然後在服務客戶端生成引用數據,並將其與Context Manager引用數據所指的結點連接起來。連接後的Binder結點與Service Server自身服務的Binder結點相對應。Binder Dirver將根據生成順序為引用數據編號,並將其傳遞給服務客戶端。服務客戶端將指定編號指定為Handler,查找Service Server的Binder結點。
服務檢索

7.3 服務使用
最後,服務客戶端將接收到的引用數據編號保存到Handler中,把與服務函數相關的RPC代碼和RPC數據包含進IPC數據中,發送給Service Server,並調用A中的函數。
服務調用


(八)從進程的角度看服務的使用

服務客戶端在使用的時候需經歷以下三個階段,無論使用何種系統服務都要經歷以下三個階段。

服務注冊【Service Server與Context Manager間的IPC】 服務檢索【服務客戶端與Context Manager間的IPC】 服務使用【服務客戶端與Service Server間的IPC】

8.1 服務注冊
服務注冊是指將Service Server中的服務注冊到Context Manager的服務列表中。其中涉及到Context Manager和Service Server兩個進程,它們的所用如下圖:
服務注冊階段
過程如下:
進程服務注冊

(1)-(3)首先Context Manager調用open()函數打開Binder Dirver,而後調用mmap函數在內核空間中開辟一塊用於接收IPC數據的Buffer,再調用ioct1()函數進入待機狀態等待接收IPC數據 (4)-(5)為了注冊服務,Service Server先打開Binder Dirver,而後調用mmap()函數確定一塊Buffer,用於接收IPC應答數據 (6)Service Server生成IPC數據,IPC數據包含RPC數據、RPC代碼和Handler為0三部分 (7)Service Server調用ioct1()函數向Binder Dirver傳遞數據。而後Binder Dirver將來自Service Server的IPC數據傳遞給Context Manager (8)-(9)Context Manager分析IPC數據中的RPC代碼,並根據RPC代碼調用相應的服務注冊函數嗎,而後使用RPC數據中的服務名稱,將指定的服務注冊到服務列表中 (10)服務注冊完成後,Context Manager會生成IPC應答數據,並傳遞給Service Server告知服務已經正常注冊,完成Binder IPC循環

8.2 服務檢索
服務客戶端在使用Service Server的服務時,會向Context Manager請求服務的編號,這一個過程稱為服務檢索,涉及到的兩個進程如下所示:
服務檢索階段
過程如下:
進程服務檢索

(1)服務注冊完成後,Context Manager進入待機狀態,等待接收數據 (2)-(4)為了向Context Manager傳遞IPC數據,服務客戶端大陸開Binder Dirver,而後調用mmap()函數准備一塊Buffer用於接收IPC應答數據。服務客戶端生成IPC數據【Handler值為0】 (5)服務客戶端調用ioct1()函數向Binder Dirver傳遞IPC數據。Binder Dirver根據IPC數據中的Handler將IPC數據傳遞給Context Manager (6)-(8)Context Manager分析接收到的IPC數據,根據RPC代碼,調用服務檢索函數。相關函數根據RPC數據中的服務名稱在服務列表中檢索服務,查找到服務Binder結點編號。Context Manager將查找到的Binder結點編號插入到IPC應答數據中,傳遞給服務客戶端 服務客戶端接收IPC應答數據,獲得指定服務的Binder結點 (9)服務客戶端接收IPC應答數據,獲得指定服務的Binder結點編號

8.3 服務使用
在服務的使用階段,服務客戶端將實際使用的Service Server的服務。在此過程中,涉及到兩個進程。如圖:
服務使用階段
過程如下:
進程服務使用

(1)如Context Manager一樣,Service Server也會進入到待機狀態,等待接收IPC數據。並且當處理完接收的IPC數據後,它將再次進入到待機狀態,等待接收新的IPC數據 (2)-(3)為了使用服務,服務客戶端首先生成IPC數據,IPC數據由RPC代碼、RPC數據、Handler組成。然後調用ioct1()函數,將IPC數據傳遞給Binder Dirver。最後Binder Dirver根據IPC數據中的Handler把IPC數據傳遞給Service Server (4)-(5)Service Server 分析IPC數據中的RPC代碼,根據RPC代碼調用服務函數。IPC數據中包含的RPC數據類似於函數的參數,在函數內部使用。當指定的服務函數執行完畢後,Service Server會生成IPC應答數據,其中包含著Binder結點編號,而後將IPC應答數據發送到服務客戶端,告知服務函數已經執行完畢 (6)服務客戶端接收IPC應答數據,並進行處理

(九)Context Manager

Context Manager,管理服務的注冊和檢索,采用C語言編寫以便使其與Binder Dirver緊密銜接。它先於Service Server與服務客戶端運行,首先進入接收IPC數據的待機狀態,處理來自於Service Server或者服務客戶端的請求。Context Manager的main函數大致分為三部分:

binder_open函數【用來打開Binder Dirver並創建IPC數據接收Buffer】 binder_become_context_manager函數【將自身的Binder結點Handler設置為0】 binder_loop函數【用來不斷的接收IPC數據】
  1. 上一頁:
  2. 下一頁: