Android進(jìn)程間Binder機(jī)制服務(wù)端及客戶端C++實(shí)現(xiàn)分析
(2012-02-06 22:12)
接觸過android的人都知道Binder服務(wù)調(diào)用是android系統(tǒng)的基礎(chǔ)。它擔(dān)負(fù)是跨進(jìn)程或進(jìn)程內(nèi)調(diào)用和數(shù)據(jù)傳遞的任務(wù)。理解它是理解android眾多services的基礎(chǔ)。binder服務(wù)的層次圖如下: 從圖中看出,一個(gè)binder服務(wù)基本分為3層:第一層業(yè)務(wù)層,它是服務(wù)的主體;第二層是粘合層,它把服務(wù)的主體和下層的binder層粘合在一起,在這一層上,可以進(jìn)行transact()調(diào)用;第三層是binder層,它負(fù)責(zé)與binder驅(qū)動(dòng)交互,完成跨進(jìn)程數(shù)據(jù)傳遞。下面從服務(wù)端實(shí)現(xiàn)說起: Binder服務(wù)的C++實(shí)現(xiàn)分析 BnXXXService是由模板類BnInterface生成的,BnInterface扮演粘合劑的角色,它把服務(wù)主體接口(IXXXService)和服務(wù)載體(BBinder)粘和在一起。它定義在frameworks/base/include/binder/IInterface.h:
一個(gè)新的服務(wù)實(shí)體類BnXXXService一般用下面的方式定義:
模板展開后,相當(dāng)于:
這樣BnXXXService同時(shí)繼承于IXXXService和BBinder。IXXXService是服務(wù)的接口,具體的服務(wù)函數(shù)在BnXXXService中實(shí)現(xiàn)。必須重載BnXXXService::onTransact(),在其中對不同的請求code,調(diào)用不同的函數(shù)。BBinder是服務(wù)的載體。當(dāng)客戶端發(fā)起服務(wù)請求,binder驅(qū)動(dòng)找出相應(yīng)服務(wù)的binder對象,這個(gè)binder對象就是BBinder,返回給IPCThreadState,IPCThreadState調(diào)用BBinder::transact(),如下面1028行代碼所示:
1028行調(diào)用BBinder::tranact()。BBinder::tranact()是:
107行調(diào)用的onTransact(),其實(shí)就是BnXXXService::onTransact()。這樣就可以在BnXXXService::onTransact()中通過switch語句完成各種各樣的服務(wù)。有關(guān)類的關(guān)系如圖: ![]() 由此看出:BnXXXService包含兩部分:一是IXXXService,服務(wù)的主體的接口;另一部分是BBinder,它是服務(wù)的載體,它和binder驅(qū)動(dòng)共同工作,保證客戶的請求最終是對一個(gè)binder對象(BBinder類)的調(diào)用。從binder驅(qū)動(dòng)的角度,每一個(gè)服務(wù)就是一個(gè)BBinder類,binder驅(qū)動(dòng)負(fù)責(zé)找出服務(wù)對應(yīng)的BBinder類。然后把這個(gè)BBinder類返回給IPCThreadState,IPCThreadState調(diào)用BBinder的transact()。BBinder的transact()又會(huì)調(diào)用onTransact()。BBinder::onTransact()是虛函數(shù),所以實(shí)際實(shí)際是調(diào)用BnXXXService::onTransact(),這樣就可在BnXXXService::onTransact()中完成具體的服務(wù)函數(shù)的調(diào)用。
BnXXXService可以用下面的方法以名字“xxx.xxx.serviceName”向ServiceManager注冊:
Binder客戶端C++實(shí)現(xiàn)分析 如果說BnInterface是服務(wù)端服務(wù)主體和載體的粘和劑,那么BpInterface就是客戶端代理和binder載體的粘合劑。它的定義:
與服務(wù)端類似,客服端一般也用下面的方式得到客戶端的服務(wù)代理:
如代碼所示:先通過defaultServiceManager()得到IServiceManager的客戶代理,然后這個(gè)IServiceManager對象查詢"IXXXService.name"服務(wù),ServiceManager::getService()返回對應(yīng)服務(wù)的IBinder。最后,interface_cast把這個(gè)IBinder轉(zhuǎn)換成服務(wù)的客戶端代理類BpXXXService。interface_cast的定義如下,
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ const android::String16 I##INTERFACE::descriptor(NAME); \ const android::String16& \ I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ } \ android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ const android::sp<android::IBinder>& obj) \ { \ android::sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \ I##INTERFACE::I##INTERFACE() { } \ I##INTERFACE::~I##INTERFACE() { } \ 關(guān)鍵在:如果obj是BBinder,obj->queryLocalInterface()返回接口本身;如果是BpBinder,則返回NULL。利用這個(gè)特性,當(dāng)queryLocalInterface()返回NULL時(shí),程序構(gòu)造一個(gè)BpXXXService。這就是interface_cast(const sp<IBinder>& obj)返回的客戶端代理類BpXXXService。 這里有個(gè)細(xì)節(jié),binder驅(qū)動(dòng)實(shí)際上返回的是服務(wù)的句柄(handle),而getService返回的是IBinder。這中間發(fā)生了什么?看看getService(),getSerivice()調(diào)用checkService():
CHECK_SERVICE_TRANSACTION的結(jié)果放在reply,binder驅(qū)動(dòng)返回的服務(wù)句柄放在reply中,它應(yīng)該在Parcel::readStrongBinder()中被轉(zhuǎn)換成sp<IBinder>。看看Parcel::readStrongBinder()
Parcel::readStrongBinder()調(diào)unflatten_binder()。在unflatten_binder()里,由于binder驅(qū)動(dòng)返回的是handle,所以ProcessState::getStrongProxyForHandle()被調(diào)用。
如果應(yīng)用是第一次請求服務(wù),那lookupHandleLocked(handle)應(yīng)該返回Null 。這樣ProcessState::getStrongProxyForHandle()構(gòu)造一個(gè)以handle為參數(shù)構(gòu)造BpBinder。這個(gè)BpBinder就是getService()得到IBinder。這樣這個(gè)至關(guān)重要的handle被保存在BpBinder里。這個(gè)BpBinder也是interface_cast(const sp<IBinder>& obj)中輸入?yún)?shù)的IBinder。 客戶端涉及的類關(guān)系圖:
到此為止,我們大致勾畫出binder調(diào)用的過程,服務(wù)端用BnInterface模板,把具體服務(wù)的接口和BBinder結(jié)合起來生成一個(gè)服務(wù)類。然后把這個(gè)服務(wù)類向ServiceManager注冊,注冊簡單地說就是把一個(gè)服務(wù)的名字和它對應(yīng)的BBinder的句柄(handle)在ServiceManager中關(guān)聯(lián)起來。以后有人需要這個(gè)服務(wù),可以用名字得到它的句柄,用這個(gè)句柄,binder驅(qū)動(dòng)就可以找到具體的BBinder服務(wù)類了。
客戶端用BpInterface模板,把具體服務(wù)的接口和BpBinder結(jié)合起來生成一個(gè)客戶端代理類。客戶端代理類的實(shí)質(zhì)就是一個(gè)服務(wù)句柄,這個(gè)句柄從binder驅(qū)動(dòng)中返回給應(yīng)用層,應(yīng)用層再用Parcel::readStrongBinder()把它轉(zhuǎn)換成sp<IXXXService>,并把它保存在BpBinder。 |
|