當前位置:編程學習大全網 - 腳本源碼 - Android通信方式篇(七)-Binder機制(Native層(下))

Android通信方式篇(七)-Binder機制(Native層(下))

本篇文章針對向ServiceManager註冊服務 和 獲取服務兩個流程來做總結。在這兩個過程中,ServiceManager都扮演的是服務端,與客戶端之間的通信也是通過Binder IPC。

在此之前先了解下Binder的進程與線程的關系:

用戶空間 :ProcessState描述壹個進程,IPCThreadState對應壹個進程中的壹個線程。

內核空間 :binder_proc描述壹個進程,統壹由binder_procs全局鏈表保存,binder_thread對應進程的壹個線程。

ProcessState與binder_proc是壹壹對應的。

Binder線程池 :每個Server進程在啟動時會創建壹個binder線程池,並向其中註冊壹個Binder線程;之後Server進程也可以向binder線程池註冊新的線程,或者Binder驅動在探測到沒有空閑binder線程時會主動向Server進程註冊新的的binder線程。對於壹個Server進程有壹個最大Binder線程數限制15,(#define DEFAULT_MAX_BINDER_THREADS 15)。對於所有Client端進程的binder請求都是交由Server端進程的binder線程來處理的。我的理解是:binder線程是進程進行binder ipc時的壹條數據處理路徑。

MediaPlayerService向ServiceManager註冊過程如下:

相關類:

整個過程總結如下:

1 獲取BpServiceManager 與 BpBinder

由defaultServiceManager()返回的是BpServiceManager,同時會創建ProcessState對象和BpBinder對象。然後通過BpBinder執行transact,把真正工作交給IPCThreadState來處理。

2 BpBinder transact

Binder代理類調用transact()方法,真正工作還是交給IPCThreadState來進行transact工作。

3 通過IPCThreadState 包裝並轉換數據並進行transact事務處理

每個線程都有壹個IPCThreadState,每個IPCThreadState中都有壹對Parcel變量:mIn、mOut。相當於兩根數據管道:

最後執行talkWithDriver。

writeTransactionData:將BC Protocol + binder_transaction_data結構體 寫入mOut, 然後執行waitForResponse:

由talkWithDriver將數據進壹步封裝到binder_write_read結構體,通過ioctl(BINDER_WRITE_READ)與驅動通信。同時等待驅動返回的接收BR命令,從mIn取出返回的數據。

mIn包裝的數據結構(註冊服務handle = 0 ,code 為ADD_SERVICE_TRANSACTION):

4 Binder Driver

把binder_write_read結構體write_buffer裏數據取出來,分別得到BC命令和封裝好數據的事務binder_transaction_data, 然後根據handler,在當前binder_proc中,找到相應的binder_ref,由binder_ref再找到目標binder_node實體,由目標binder_node再找到目標進程binder_proc。然後就是插入數據:當binder驅動可以找到合適的線程,就會把binder_transaction節點插入到servciemanager的線程的todo隊列中,如果找不到合適的線程,就把節點之間插入servciemanager的binder_proc的todo隊列。

5 ServiceManager

經過Binder Driver的處理,數據已經到了ServiceManager進程,在BR_TRANSACTION的引導下,在binder_loop()中執行binder_parser()取出數據,執行do_add_service()操作,最終向 svcinfo 列表中添加已經註冊的服務(沒有數據的返回)。最後發送 BR_REPLY 命令喚醒等待的線程,通知註冊成功。結束MediaPlayerService進程 waitForResponse()的狀態,整個註冊過程結束。

獲取服務的過程與註冊類似,首先 ServiceManager 向 Binder 驅動發送 BC_TRANSACTION 命令攜帶 CHECK_SERVICE_TRANSACTION 命令,同時獲取服務的線程進入等待狀態 waitForResponse()。Binder 驅動收到請求命令向 ServiceManager 的發送 BC_TRANSACTION 查詢已註冊的服務,會區分請求服務所屬進程情況。

查詢到直接響應 BR_REPLY 喚醒等待的線程。若查詢不到將與 binder_procs 鏈表中的服務進行壹次通訊再響應。

以startService為例來簡單總結下執行流程:

3.1 從方法執行流程來看:

Client :

1 AMP.startService 標記方法以及通過Parcel包裝數據;

2 BinderProxy.transact 實際調用native的 android_os_BinderProxy_transact 傳遞數據;

3 獲取BpServiceManager 與 BpBinder 同時會創建ProcessState。然後通過BpBinder執行transact,把真正工作交給IPCThreadState來處理;

4 IPC.transact 主要執行writeTransactionData,將上層傳來的數據重新包裝成binder_transaction_data,並將BC Protocol + binder_transaction_data結構體 寫入mOut;

5 IPC waitForResponse talkWithDriver + 等待返回數據;

6 talkWithDriver 將數據進壹步封裝成binder_write_read,通過ioctl(BINDER_WRITE_READ)與驅動通信;

Kernel :

7 binder ioctl 接收BINDER_WRITE_READ ioctl命令;

8 binder_ioctl_write_read 把用戶空間數據ubuf拷貝到內核空間bwr;

9 binder_thread_write 當bwr寫緩存有數據,則執行binder_thread_write;當寫失敗則將bwr數據寫回用戶空間並退出;

10 binder_transaction 找到目標進程binder_proc並插入數據到目標進程的線程todo隊列,最終執行到它

時,將發起端數據拷貝到接收端進程的buffer結構體;

11 binder_thread_read 根據binder_transaction結構體和binder_buffer結構體數據生成新的binder_transaction_data結構體,寫入bwr的read_buffer,當bwr讀緩存有數據,則執行binder_thread_read;當讀失敗則再將bwr數據寫回用戶空間並退出;最後,把內核數據bwr拷貝到用戶空間ubuf。

12 binder_thread_write + binder_ioctl BR命令和數據傳遞

Server:

13 IPC.executeCommand 解析kernel傳過來的binder_transaction_data數據,找到目標BBinder並調用其transact()方法;

14 IPC.joinThreadPool 采用循環不斷地執行getAndExecuteCommand()方法, 處理事務。當bwr的讀寫buffer都沒有數據時,則阻塞在binder_thread_read的wait_event過程. 另外,正常情況下binder線程壹旦創建則不會退出.

15 BBinder.transact 到Binder.exeTransact 調用 AMN.onTransact

16 AMN.onTransact 把數據傳遞到AMS.starService去執行

17 AMS.starService Server處理了Client的請求了

然後原路replay回去,talkWithDriver 到Kernel ,然後找到Client進程,把數據拷貝到read_buffer裏,最終喚醒IPC,把反饋傳遞回AMP.startService。完成啟動服務。

3.2 從通信協議流程來看:

非oneWay:

oneway:

oneway與非oneway區別: 都是需要等待Binder Driver的回應消息BR_TRANSACTION_COMPLETE. 主要區別在於oneway的通信收到BR_TRANSACTION_COMPLETE則返回,而不會再等待BR_REPLY消息的到來. 另外,oneway的binder IPC則接收端無法獲取對方的pid.

3.3 從數據流來看

從用戶空間開始:

進入驅動後:

回到用戶空間:

參考:

/2016/09/04/binder-start-service/

/2015/11/28/binder-summary/

/2015/11/14/binder-add-service/

/2015/11/15/binder-get-service/

  • 上一篇:笑話大全有哪些?
  • 下一篇:怎麽把qq空間圖文模塊的文字變顏色?
  • copyright 2024編程學習大全網