編輯:關於Android編程
Binder原本是IPC工具,但是在Android中它的主要作用是支持RPC(Remote Procedure Call),使得當前進程調用另一個進程的函數就像調用自身的函數是一樣輕松簡單。Binder又Service Server(含有Android的服務)、Service Client(使用服務的客戶端)、Context Manager(確定服務的位置)、以及Binder Dirver四大部分組成。
Anroid是基於Linux內核的操作平台,Android進程和Linux進程一樣,它們只運行在進程固有的虛擬地址空間中。用戶代碼與相關庫運行在用戶空間內,而內核空間中運行的代碼則運行在內核空間中的各個區域中。並且,進程具有獨立的地址空間,單獨運行。但是內核空間是被其他用戶進程所共享的。那麼兩個進程是如何相互通信的呢?顯然是要經過兩個進程共享的內核空間了。從內核的角度看,進程只不過是一個作業單位,雖然那各進程的用戶空間相互獨立,但運行在內核空間中的任務數據、代碼都是批次共享的。
服務客戶端要通過Binder IPC實現對Service Serverf的foo()函數的調用,Binder Dirver充當中間人的角色,將從服務客戶端接收到的Binder IPC數據傳遞給Service Server。具體過程如圖:
Binder IPC數據包含調用其他進程函數的信息,是Binder Dirver操作的IPC數據單位。
IPC數據包含函數調用相關的內容,她由待調服務號、待調函數名、Binder協議構成。在Android中服務號用來標記運行中的各個服務,便於區分不同的服務;待調函數名用來指定服務客戶端將調用的服務中的函數;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嘗試RPC操作時,會進行open()系統調用,獲取Binder Dirver的文件描述符。而後,通過mmap()系統調用,在內核中開辟一塊區域,以便存放IPC數據。最後,調用ioct1()函數,將IPC數據作為參數傳遞給Binder Dirver。
服務客戶端調用Service Server的服務函數的過程。如下圖所示:
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_打頭的。
首先,服務客戶端使用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應答數據發送給服務客戶端。如圖:
在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兩個進程,它們的所用如下圖:
過程如下:
8.2 服務檢索
服務客戶端在使用Service Server的服務時,會向Context Manager請求服務的編號,這一個過程稱為服務檢索,涉及到的兩個進程如下所示:
過程如下:
8.3 服務使用
在服務的使用階段,服務客戶端將實際使用的Service Server的服務。在此過程中,涉及到兩個進程。如圖:
過程如下:
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數據】