Binder進程間通信系統
Android應用程序由Activity、Service、BroadcastReceiver、ContentProvider四種類型組件構成,它們可能運行在同一進程中,也可能運行在不同進程中,此外各種系統組件也運行在獨立的進程中,例如,Activity管理服務AMS和PMS都運行在系統進程System進程中,那麼,這些運行在不同進程中的應用程序和系統組件是如何通信的呢?
Android基於Linux內核開發,Linux提供的進程間通信:
- 管道(Pipe)
- 信號(Signal)
- 消息隊列(MessageQunue)
- 共享內存(ShareMemory)
- 套接字(Socket)
Android 進程間通信 – Binder
Binder進程通信機制採用CS通信方式;
提供服務的進程 -> Server進程(可同時運行多個Service組件向Client進程提供服務)
訪問服務的進程 -> Client進程(可同時向多個Service組件請求服務,每個請求對應一個Client組件或者稱爲Service代理對象)
每一個Server進程和Client進程都維護一個Binder線程池來處理進程間通信請求
Server進程和Client進程依靠內核空間的binder驅動程序(設備文件/dev/binder)
Service組件啓動時,會將自己註冊到ServiceManager組件中以便Client組件可以通過ServiceManager組件找到它
ServiceManager組件稱爲Binder進程間通信的上下文管理者,由於它也需要和Service進程、Client進程通信,可將它看做一個特殊的Service組件。
- Service組件實現原理
- Client組件實現原理
Binder進程間通信機制涉及了Client、Service、ServiceManager、Binder四個角色;
Binder進程間通信機制的四個使用情景:
- ServiceManager的啓動過程
- ServiceManager代理對象的獲取過程
- Service組件的啓動過程
- Service代理對象的獲取過程
ServiceManager的啓動過程
ServiceManager 是由init進程負責啓動的,而init進程是在系統啓動時啓動的,腳本如下:
ServiceManager對應的程序文件servicemanager,源代碼目錄價結構:
main函數入口在service_manager.c中:
ServiceManager的啓動過程由三個步驟組成:
- 調用函數binder_open打開設備文件/dev/binder,以及將它映射到本進程的地址空間
- 調用函數binder_become_context_manager將自己註冊爲Binder進程通信機制的上下文管理者
- 調用函數binder_loop來循環等待和處理Client進程的通信請求
ServiceManager代理對象的獲取過程
ServiceManager代理對象的關係圖
由於ServiceManager的句柄值恆爲0,因此獲取它的代理對象的過程省去了與binder驅動程序交互的過程
Android系統在應用程序框架層的Binder庫中提供了一個函數defaultServiceManager來獲得一個ServiceManager代理對象
有了ServiceManager代理對象,Service組件就可以在啓動過程中使用它的函數addService將自己註冊到ServiceManager中,Client組件就可以使用它的函數getService來獲得一個指定名稱的Service組件的代理對象。
Service組件的啓動過程
Servie組件是在Server進程中運行,Service進程在啓動時,會首先將它裏面的Service組件註冊到ServiceManager中,接着再啓動一個Binder線程池來等待和處理Client組件的通信請求。
Service組件FregService是運行在FregServer進程中的
註冊Service組件
實際調用了BpServiceManager類的addServcie函數
Client進程和Server進程的一次進程間通信可劃分5個步驟:
- Client進程將進程間通信數據封裝成一個Parcel對象,以便可以將進程間通信數據傳遞給Binder驅動程序.
- Client進程向Binder驅動程序發送一個BC_TRANSACTION命令協議,Binder驅動程序根據協議內容找到目標Server進程之後,就會向Client進程發送一個BR_TRANSACTION_COMPLETE返回協議,表示它的進程間通信請求已經接受。Client進程接收到Binder驅動程序發送給它的BR_TRANSACTION_COMPLETE返回協議,並且對它進行處理之後,就會再次進入到 Binder驅動程序中等待目標Server進程返回進程通信結果。
- Binder驅動程序在向Client進程發送BR_TRANSACTION_COMPLETE返回協議的同時,也會向目標Server進程發送一個BR_TRANSACTION返回協議,請求目標Server進程處理該進程間通信請求。
- Server進程接收到Binder驅動程序發來的BR_TRANSACTION返回協議,並且對它進行處理之後,就會向Binder驅動程序發送一個BC_REPLY命令協議,Binder驅動程序根據協議內容找到目標Client進程之後,就會向Server進程發送一個BR_TRANSACTION_COMLETE返回協議,表示它返回的進程間通信結果已經收到了,Server進程接收到Binder驅動程序發送給它的BR_TRANSACTION_COMPLETE返回協議,並且對它進行處理之後,一次進程通信過程就結束了,接着它會再次進入到Binder驅動程序中等待下一次進程間通信請求。
- Binder驅動程序向Server進程發送BR_TRANSACTION_COMPLETE返回協議的同時,也會向目標Client進程發送一個BR_REPLY返回協議,表示Server進程已經處理完成它的進程間通信請求了。並且將進程間通信結果返回給它。
Client進程和Server進程其實並不需要對BR_TRANSACTION_COMPLETE返回協議做特殊處理,這樣做是爲了讓Client進程和Server進程在執行通信的過程中,有機會返回到用戶空間去做其他事情,從而增加他們的併發處理能力。
- Service代理對象的獲取過程
FregClient進程獲得運行在FregServer進程中的Service組件FregService的代理對象。
ServiceManager代理對象函數getService的實現
調用函數checkService來獲得一個名稱爲name的Service組件的代理對象。