Binder 通信架構(gòu)簡介
Binder 采用 C/S 架構(gòu),是 Android 提供的一種通信機(jī)制,通過 ServiceManager 集中管理系統(tǒng)中的有名服務(wù)。
使用服務(wù)的大致過程:
-
Server端首先向ServiceManager注冊服務(wù)以便Client可以使用(此時(shí)Server是Client端,ServiceManager是服務(wù)端) -
Client向ServiceManager請求它要使用的服務(wù)(此時(shí)Client是Client端,ServiceManager是服務(wù)端)。 -
Client根據(jù)得到的Service信息,和Server進(jìn)行通信(此時(shí)Client是Client端,Server是服務(wù)端)。
以上三步均通過 Binder 通信機(jī)制實(shí)現(xiàn),只是封裝的層次可能有所不同,理解其中任意即可知道其它。
如圖:

通信過程
這里先以 MediaServer 向 ServiceManager 注冊 MediaPlayerService 服務(wù)為例,進(jìn)行其流程的大致描述,每步后面都會(huì)對其中一些難以理解的地方進(jìn)一步說明。
注: MediaPlayerService 只是 MediaServer 向 serviceManager 注冊的眾多服務(wù)之一。
serviceManager 啟動(dòng)
注冊服務(wù)前首先要啟動(dòng)好 serviceManager 服務(wù)程序,該程序是掌管服務(wù)的服總控管理服務(wù)程序,比較特殊,它的啟動(dòng)沒有使用 Android 的封裝機(jī)制而是直接和 binder 交互。
大致過程就是:
- 設(shè)置自己的
handle,該handle為宏值BINDER_SERVICE_MANAGER,用來標(biāo)示serviceManager服務(wù)程序,也就是其它程序請求服務(wù)時(shí)的目的端。 - 打開
binder設(shè)備映射binder所需緩存 - 通過
binder的ioctl命令設(shè)置自身為serviceManager,整個(gè)系統(tǒng)中只有一個(gè)serviceManager。 - 進(jìn)入消息循環(huán),根據(jù)
handle判斷消息目標(biāo),如果是自身的handle,則處理接收到的消息。
注:其它服務(wù)程序的啟動(dòng)一般使用 android 的封裝機(jī)制,后面講述服務(wù)啟動(dòng)的時(shí)候會(huì)講述利用 android 封裝機(jī)制如何啟動(dòng)一個(gè)普通的服務(wù)。
MediaServer 向 serviceManager 注冊 MediaPlayerService 服務(wù)
1、業(yè)務(wù)層實(shí)現(xiàn)
打包數(shù)據(jù),即將標(biāo)示“注冊服務(wù)”的 AddService 關(guān)鍵字打包,至此業(yè)務(wù)層內(nèi)容完畢,余下的交由通信層處理。
注: Android 將通信和處理過程通過其封裝機(jī)制,劃分為“業(yè)務(wù)層”和“通信層”兩個(gè)部分(這點(diǎn)至關(guān)重要?。?。
- “業(yè)務(wù)層”專注對業(yè)務(wù)流程的處理,依據(jù)不同的應(yīng)用功能而不同;
- “通信層”專注對消息通信的處理,采用
Binder機(jī)制實(shí)現(xiàn),這也意味著也可用其它的通信機(jī)制實(shí)現(xiàn)此部分的功能例如“socket”、“管道”等。
2、通信層實(shí)現(xiàn)層次1- BpBinder 代理類的處理
通信層可借助 BpBinder 這個(gè)工具類來實(shí)現(xiàn),通過 BpBinder 的 Transact 函數(shù)最終傳遞數(shù)據(jù)給 ServerManager 處理。 BpBinder 通過“人手一份”的 IPCThreadState ,以線程局部變量的方式,將 BpBinder 自身、 BBinder 對應(yīng)的 handler 與數(shù)據(jù)等信息交由其 transact 函數(shù)處理。
注: BpBinder 和 BBinder 都是 Android 中與 binder 通信的代表,它們都繼承自 IBinder 類。 BpBinder 是客戶端和服務(wù)端交互的代理類, p 即 proxy 的意思; BBinder 則是與 BpBinder 相對的一端,是 proxy 的目的端。兩者一個(gè)是客戶端,一個(gè)是服務(wù)端,并且一一對應(yīng),和 BpBinder 對應(yīng)的 BBbinder 用一個(gè) Bpbinder 的 handler 成員( mHandler )來索引到。
3、通信層實(shí)現(xiàn)層次2- 和驅(qū)動(dòng)的交互
IPCThreadState 對象包含:
-
mIn,包含用于接收數(shù)據(jù)的緩存和操作。 -
mOut,包含用于發(fā)送數(shù)據(jù)的緩存和操作。 -
mProcess,包含binder通信所需的具體文件描述符內(nèi)存
IPCThreadState 的 transact 函數(shù)首先將數(shù)據(jù)發(fā)送至其 mOut 成員中,然后通過 talkWithDriver 函數(shù)與 binder 驅(qū)動(dòng)交互(即發(fā)送請求到 binder 設(shè)備并接收回復(fù)到 mIn 中)后,從 mIn 中取出相應(yīng)的回復(fù)信息,并調(diào)用 executeCommand 函數(shù)進(jìn)行進(jìn)一步的處理。
注: talkWithDriver 中,通過 ioctl 的方式與驅(qū)動(dòng)交互。這里使用 BINDER_WRITE_READ 命令將 mOut 的數(shù)據(jù)發(fā)送給 driver ,然后接收消息到 mIn 中。(這里,我們需要注意,一般在處理不同命令的分支中,發(fā)送給設(shè)備驅(qū)動(dòng)的分支命令碼是 BC_XXX ,設(shè)備回復(fù)的命令碼是 BR_XXX )
4、通信層實(shí)現(xiàn)層次3- BBinder 的處理
在 executeCommand 函數(shù)中,借助回復(fù)得到的 BBinder 這個(gè)工具類對象,調(diào)用其 transact 函數(shù)進(jìn)行處理(若 server 死掉,則由 BpBinder 處理)。
注:此時(shí)客戶端接收回復(fù),相當(dāng)于服務(wù)器的“服務(wù)端”,這個(gè) BBinder 也是客戶端做為服務(wù)服務(wù)端的代表,具體這個(gè) BBinder 的處理情況,可參考后面服務(wù)端的處理過程。
5、通信層實(shí)現(xiàn)層次4- 服務(wù)端的工作
客戶端程序發(fā)送信息后,服務(wù)端在接收消息循環(huán)中接收到消息并開始處理。這里因?yàn)槭窍?ServerManager 發(fā)送注冊服務(wù)請求,而 ServerManager 這個(gè)服務(wù)程序比較特殊,沒有使用 BBinder 、 BnXXX 之類的封裝工具接口,它是直接使用操作 binder 提供的相關(guān)接口完成這個(gè)過程的。
至此,我們分兩種方式講解此處內(nèi)容:
5.1、在 ServerManager 中實(shí)際的處理
直接在其循環(huán)中調(diào)用 binder 的 ioctl 接口接收到消息,然后再進(jìn)行相關(guān)處理,再通過 binder 的 ioctl 接口回復(fù)消息給請求方。
5.2、正常 Server 程序的處理
一般 Server 都至少有一個(gè)線程處于接收消息的循環(huán)中,假設(shè)其中一個(gè)線程接收到客戶端發(fā)送來的消息,最終會(huì)調(diào)用到 executeCommand 函數(shù)進(jìn)一步處理。
處理過程如前所述:
- 從接收到的消息中,取得代表自己的
BBinder對象, - 進(jìn)入
BBinder::transact函數(shù), - 再調(diào)用
onTransact處理通信的內(nèi)容, - 在
onTransact中調(diào)用業(yè)務(wù)函數(shù)處理業(yè)務(wù)邏輯的內(nèi)容。
注:這里調(diào)用的 BBinder::onTransact ,其實(shí)指向的是其子類對象的函數(shù),即 BnXXX ;而其中調(diào)用的業(yè)務(wù)函數(shù),也是其子類對象自己實(shí)現(xiàn)的函數(shù),即 XXXService 。具體是什么子類,依據(jù)服務(wù)有所不同,以剛剛注冊的 MediaPlayerService 為例,其它類似,涉及的相關(guān)類如下圖:

我們實(shí)現(xiàn) MediaPlayerService 的業(yè)務(wù)功能(如 createMediaRecorder )時(shí),就實(shí)現(xiàn) MediaPlayerService 子類的函數(shù)。處理通信信息時(shí)(如根據(jù)不同類型的信息,調(diào)用不同的業(yè)務(wù)函數(shù)),實(shí)現(xiàn) BnMediaPlayerService 子類的函數(shù)。
服務(wù)端啟動(dòng)
前面講述的服務(wù)注冊過程只是服務(wù)程序啟動(dòng)的一個(gè)階段,這個(gè)階段服務(wù)程序做為 serviceManager 的客戶端,向 serviceManager 程序請求注冊服務(wù)。當(dāng)注冊完服務(wù)后,服務(wù)程序本身便可做為服務(wù)端,進(jìn)入自己的消息循環(huán),接收客戶端的請求,和 serviceManager 不同的是, serviceManager 啟動(dòng)時(shí)直接與 binder 交互,而一般服務(wù)端通過 android 封裝的機(jī)制來啟動(dòng)。
這里還是以 MediaServer 的啟動(dòng)為例,介紹啟動(dòng)的大致過程:
1、獲得 ProcessState 單實(shí)例對象
每個(gè)進(jìn)程啟動(dòng)時(shí),都通過單實(shí)例方式創(chuàng)建一個(gè)唯一的 ProcessState ,它主要打開 binder 設(shè)備文件,以及通過 mmap 映射好通信所需的內(nèi)存地址,相關(guān)信息在其成員中保存。后面使用 binder 通信時(shí),最終會(huì)用到這里的內(nèi)容。
2、獲得 IServiceManager 單實(shí)例對象以便和 serviceManager 進(jìn)程交互
這里通過 defaultServiceManager 函數(shù),以單實(shí)例方式進(jìn)行。
- 首先創(chuàng)建
BpBinder對象,該對象由serviceManager對應(yīng)的handle初始化,完成通信層功能; - 然后通過該
BpBinder,轉(zhuǎn)換生成IServiceManager對象(其實(shí)是子類BpServerManager對象),完成業(yè)務(wù)層功能; -
BpBinder對象做為IServiceManager對象的成員存在,以這種方式將業(yè)務(wù)層和通信層相關(guān)聯(lián)。
交互實(shí)現(xiàn)的關(guān)鍵
-
通信層、業(yè)務(wù)層、通信業(yè)務(wù)關(guān)聯(lián)
-
通信層相關(guān)內(nèi)容
根據(jù)前面,
serviceManager的handle是BINDER_SERVICE_MANAGER,一般就是0,這個(gè)為系統(tǒng)所周知。借助該handle做為成員構(gòu)成的BpBinder代理對象,來向serviceManager發(fā)送消息協(xié)助完成通信層的功能。服務(wù)端會(huì)通過接受到消息中的handle比對,判斷出是否為發(fā)送給自己的消息。 -
業(yè)務(wù)層相關(guān)內(nèi)容
生成的
BpBinder對象,會(huì)最終通過interface_cast,轉(zhuǎn)換成IServiceManager對象,完成serviceManager應(yīng)用程序?qū)?yīng)的業(yè)務(wù)功能(如:getService、addService等)。 -
通信層和業(yè)務(wù)層的關(guān)聯(lián)
是利用
BpBinder創(chuàng)建BpServiceManager對象,使用BpBinder是通過BpServiceManager對象的mRemote成員來做到的。
期間所涉及的類關(guān)系如下:
-

-
實(shí)現(xiàn)通信層、業(yè)務(wù)層類的關(guān)系
對于前面的類圖,我們還是從“業(yè)務(wù)層”和“通信層”兩個(gè)方面來看。
-
業(yè)務(wù)層
BpServiceManager、BnServiceManager都繼承自IServiceManager,通過IServiceManager完成業(yè)務(wù)邏輯功能,通過其子類實(shí)現(xiàn)業(yè)務(wù)邏輯,其中BnServiceManager的功能需要又由子類MyServiceManager來實(shí)現(xiàn)。 -
通信層
通過
IBinder完成通信相關(guān)邏輯,具體實(shí)現(xiàn)由其子類:BpBinder完成客戶代理功能,BBinder完成服務(wù)端功能。而實(shí)現(xiàn)又是借助于封裝的BpServiceManager和BnServiceManager完成的。BnServiceManager繼承自BBinder;而BpServiceManager通過父類BpInterface的父類BpRefBase的mRemote成員,與BpBinder對象關(guān)聯(lián)。
-
總結(jié)
結(jié)合前面描述“正常
server程序的處理”中的“MediaPlayerService家譜”圖,我們可大致理清Android封裝機(jī)制對“業(yè)務(wù)層”和“通信層”的封裝機(jī)制。而兩者間的關(guān)聯(lián),正是BnServerXXX和BpServiceXXX即能涉及業(yè)務(wù)相關(guān)的內(nèi)容,也能涉及通信相關(guān)內(nèi)容的原因。
-

服務(wù)端啟動(dòng)后,與客戶端的交互過程,與服務(wù)程序本身做為客戶端向 `serviceManager` 注冊服務(wù)的過程類似,參見后面講述“客戶端和服務(wù)端交互”時(shí)的內(nèi)容。這里著重講述 `Android` 系統(tǒng)中,大部分服務(wù)程序是如何利用 `Android` 的封裝機(jī)制實(shí)現(xiàn)啟動(dòng),以便后續(xù)的客戶端能向注冊服務(wù)一般向該服務(wù)程序請求服務(wù)的。
3、向 serviceManager 注冊各類服務(wù)
前面注冊的 MediaPlayerService ,只是 MediaServer 的眾服務(wù)之一,它使用 MediaPlayerService::instantiate 函數(shù),調(diào)用通過 defaultServiceManager 函數(shù)返回的 IServiceManager 的 addService 業(yè)務(wù)接口實(shí)現(xiàn)。
注冊期間 MediaServer 做為 serviceManager 的客戶端,向 serviceManager 程序請求注冊服務(wù);其它服務(wù)的注冊類似,其詳細(xì)過程參考前面講述的 “ MediaServer 向 serviceManager 注冊 MediaPlayerService 服務(wù)” 相關(guān)內(nèi)容。
4、服務(wù)端進(jìn)入自己的消息循環(huán)
通過 StartThreadPool 和 JoinThreadPool 實(shí)現(xiàn)。
啟動(dòng)的這些線程,進(jìn)入消息循環(huán)統(tǒng)一為前面各類服務(wù)工作。如果任務(wù)不繁重,可以不用 StartThreadPool ,使用主線程即可。
客戶端和服務(wù)端交互
這里,以客戶端與MediaPlayerService服務(wù)的交互為例
1、客戶端向 ServiceManager 查詢 MediaPlayerService 服務(wù)
- 首先客戶端通過
defaultServiceManage函數(shù)獲取到代表serviceManage的IServiceManager接口; - 然后通過
IServerManager的getService業(yè)務(wù)接口,獲取到MediaPlayerService的BpBinder; - 最后將獲取的
BpBinder通過interface_cast轉(zhuǎn)換成IMediaPlayerService接口,做為獲取的結(jié)果。
2、客戶端向服務(wù)端發(fā)送服務(wù)請求
ImediaPlayerService 接口包含了 MediaPlayerService 可提供的各種業(yè)務(wù)接口函數(shù)供客戶端使用,大致過程是:
- 客戶端的業(yè)務(wù)層(
BpMediaPlayerService相關(guān))打包數(shù)據(jù)遞交給通信層; - 客戶端通信層(
BpBinder相關(guān))將數(shù)據(jù)發(fā)送給Binder驅(qū)動(dòng)。
這里客戶端發(fā)送數(shù)據(jù)時(shí)涉及到從業(yè)務(wù)層到通信層的過程(類似數(shù)據(jù)打包),之后我們可以看到,通過 Binder 驅(qū)動(dòng),在服務(wù)端接收數(shù)據(jù)時(shí)會(huì)經(jīng)歷從通信層到業(yè)務(wù)層的過程(類似數(shù)據(jù)解包)。
注:這些業(yè)務(wù)接口目前還是在客戶端被調(diào)用,實(shí)際調(diào)用的是子類 BpMediaPlayerService ,這是一個(gè)代理接口,客戶端通過繼承自 IMediaPlayerService 的 BpMediaPlayerService 代理接口來調(diào)用各種業(yè)務(wù)接口請求服務(wù)端的服務(wù),在代理接口的業(yè)務(wù)函數(shù)中將封裝好的信息借助其通信層的代理 BpBinder 類發(fā)送給內(nèi)核 Binder 設(shè)備的驅(qū)動(dòng),之后的過程在服務(wù)端的處理中可以看到。
3、服務(wù)端處理收到的客戶端請求
這里的內(nèi)容在前面講述注冊服務(wù)過程時(shí)的 “正常 Server 程序的處理” 中已經(jīng)詳細(xì)講述,可參考相關(guān)內(nèi)容。
大致過程是:
- 服務(wù)端的通信層接收到請求(
BBinder相關(guān)); - 遞交給服務(wù)端的業(yè)務(wù)層處理(
BnMediaPlayerService相關(guān))。
這里,服務(wù)端通過調(diào)用同樣繼承自 IMediaPlayerService 的 BnMediaplayerService 業(yè)務(wù)接口,來實(shí)現(xiàn)客戶端用 BpMediaPlayerService 業(yè)務(wù)接口中的對應(yīng)的各種業(yè)務(wù)接口,客戶端調(diào)用時(shí)采用的是代理接口的業(yè)務(wù)函數(shù),和服務(wù)端服務(wù)時(shí)對應(yīng)的真正實(shí)現(xiàn)的業(yè)務(wù)函數(shù),因?yàn)閬碜酝桓割?,一般都是相同的函?shù)簽名。
注:
Binder 驅(qū)動(dòng)通過客戶端通過 BpBinder 發(fā)送來的 handle 找到在驅(qū)動(dòng)中對應(yīng)的 Server 端通信層的 BBinder ,將數(shù)據(jù)傳送到服務(wù)端的業(yè)務(wù)層,在服務(wù)端有一個(gè)和 BpMediaPlayerService 繼承自同一個(gè)父類的 BnMediaPlayerservice 接口,其中的業(yè)務(wù)函數(shù)才是真正的業(yè)務(wù)實(shí)現(xiàn),該業(yè)務(wù)接口的業(yè)務(wù)函數(shù)收到 BBinder 通信端傳上來的信息后,調(diào)用相應(yīng)的真正實(shí)現(xiàn)了的業(yè)務(wù)函數(shù)進(jìn)行業(yè)務(wù)處理。
其他
參考資料:
- 《深入理解Android 卷I》