Binder 系列總結


 轉載:http://gityuan.com/2015/11/28/binder-summary/

1. Binder概述

  1. 從IPC角度來說:Binder是Android中的一種跨進程通信方式,該通信方式在linux中沒有,是Android獨有;
  2. 從Android Driver層:Binder還可以理解為一種虛擬的物理設備,它的設備驅動是/dev/binder;
  3. 從Android Native層:Binder是創建Service Manager以及BpBinder/BBinder模型,搭建與binder驅動的橋梁;
  4. 從Android Framework層:Binder是各種Manager(ActivityManager、WindowManager等)和相應xxxManagerService的橋梁;
  5. 從Android APP層:Binder是客戶端和服務端進行通信的媒介,當bindService的時候,服務端會返回一個包含了服務端業務調用的 Binder對象,通過這個Binder對象,客戶端就可以獲取服務端提供的服務或者數據,這里的服務包括普通服務和基於AIDL的服務。

2. Binder架構

binder_arch

Binder在整個Android系統中有這舉足輕重的地位,在Native層有一套完整的binder通信的C/S架構(圖中的藍色),Bpinder作為客戶端,BBinder作為服務端。基於naive層的Binder框架,Java也有一套鏡像功能的binder C/S架構,通過JNI技術,與native層的binder對應,Java層的binder功能最終都是交給native的binder來完成。從kernel到native,jni,framework層的架構所涉及的所有有關類和方法見 Binder類圖

3. Binder進程與線程

binder_proc_relation

對於底層Binder驅動,通過binder_procs鏈表記錄所有創建的binder_proc結構體,binder驅動層的每一個binder_proc結構體都與用戶空間的一個用於binder通信的進程一一對應,且每個進程有且只有一個ProcessState對象,這是通過單例模式來保證的。在每個進程中可以有很多個線程,每個線程對應一個IPCThreadState對象,IPCThreadState對象也是單例模式,即一個線程對應一個IPCThreadState對象,在Binder驅動層也有與之相對應的結構,那就是Binder_thread結構體。在binder_proc結構體中通過成員變量 rb_root threads,來記錄當前進程內所有的binder_thread。

Binder線程池:每個Server進程在啟動時會創建一個binder線程池,並向其中注冊一個Binder線程;之后Server進程也可以向binder線程池注冊新的線程,或者Binder驅動在探測到沒有空閑binder線程時會主動向Server進程注冊新的的binder線程。對於一個Server進程有一個最大Binder線程數限制,默認為16個binder線程,例如Android的system_server進程就存在16個線程。對於所有Client端進程的binder請求都是交由Server端進程的binder線程來處理的。

4. Binder傳輸過程

Binder IPC機制,就是指在進程間傳輸數據(binder_transaction_data),一次數據的傳輸,稱為事務(binder_transaction)。對於多個不同進程向同一個進程發送事務時,這個同一個進程或線程的事務需要串行執行,在Binder驅動中為binder_proc和binder_thread都有todo隊列。

也就是說對於進程間的通信,就是發送端把binder_transaction節點,插入到目標進程或其子線程的todo隊列中,等目標進程或線程不斷循環地從todo隊列中取出數據並進行相應的操作。

binder_transaction

在Binder驅動層,每個接收端進程都有一個todo隊列,用於保存發送端進程發送過來的binder請求,這類請求可以由接收端進程的任意一個空閑的binder線程處理;接收端進程存在一個或多個binder線程,在每個binder線程里都有一個todo隊列,也是用於保存發送端進程發送過來的binder請求,這類請求只能由當前binder線程來處理。binder線程在空閑時進入可中斷的休眠狀態,當自己的todo隊列或所屬進程的todo隊列有新的請求到來時便會喚醒,如果是由所需進程喚醒的,那么進程會讓其中一個線程處理響應的請求,其他線程再次進入休眠狀態。

5. Binder路由

先來看看Native Binder IPC的兩個重量級對象:BpBinder(客戶端)和BBinder(服務端)都是Android中Binder通信相關的代表,它們都從IBinder類中派生而來,關系圖如下:

Binder關系圖

  • IBinder有一個重要方法queryLocalInterface, 默認返回值為NULL;
    • BBinder/BpBinder都沒有實現,默認返回NULL;BnInterface重寫該方法;
    • BinderProxy(Java)默認返回NULL;Binder(Java)重寫該方法;
  • IInterface有一個重要方法asBinder;
  • IInterface子類(服務端)會有一個方法asInterface;

Native層通過宏IMPLEMENT_META_INTERFACE來完成asInterface實現和descriptor的賦值過程;

對於Java層跟Native一樣,也有完全對應的一套對象和方法:

  • 例如ActivityManagerNative, 通過實現asInterface方法,以及其通過其構造函數 調用attachInterface(),完成descriptor的賦值過程。
  • 再如AIDL全自動生成asInterface和descriptor賦值過程。

同一個進程,請求binder服務,不需要創建binder_ref,BpBinder等這些對象,但是是否需要經過binder call,取決於descriptor是否設置。 這就涉及到Java服務Native使用,或許Native服務在Java層使用,需要格外注意。

binder的路由原理:BpBinder發送端,根據handler,在當前binder_proc中,找到相應的binder_ref,由binder_ref再找到目標binder_node實體,由目標binder_node再找到目標進程binder_proc。簡單地方式是直接把binder_transaction節點插入到binder_proc的todo隊列中,完成傳輸過程。

對於binder驅動來說應盡可能地把binder_transaction節點插入到目標進程的某個線程的todo隊列,效率更高。當binder驅動可以找到合適的線程,就會把binder_transaction節點插入到相應線程的todo隊列中,如果找不到合適的線程,就把節點之間插入binder_proc的todo隊列。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM