在
Zygote啟動(dòng)過(guò)程 一文中我們說(shuō)道,Zygote一生中最重要的一件事就是生下了 System Server 這個(gè)大兒子,System Server 擔(dān)負(fù)著提供系統(tǒng) Service的重任,在深入了解這些Service 之前,我們首先要了解 什么是Service?它的工作原理是什么?
1. Service是什么?
簡(jiǎn)單來(lái)說(shuō),Service就是提供服務(wù)的代碼,這些代碼最終體現(xiàn)為一個(gè)個(gè)的接口函數(shù),所以,Service就是實(shí)現(xiàn)一組函數(shù)的對(duì)象,通常也稱為組件。Android 的Service 有以下一些特點(diǎn):
請(qǐng)求Service服務(wù)的代碼(Client) 和 Service本身(Server) 不在一個(gè)線程,很多情況下不在一個(gè)進(jìn)程內(nèi)??邕M(jìn)程的服務(wù)稱為遠(yuǎn)端(Remote)服務(wù),跨進(jìn)程的調(diào)用稱為IPC。通常應(yīng)用程序通過(guò)代理(Proxy)對(duì)象來(lái)訪問(wèn)遠(yuǎn)端的Service。
Service 可以運(yùn)行在native 端(C/C++),也可以運(yùn)行在Java 端。同樣,Proxy 可以從native 端訪問(wèn)Java Service, 也可以從Java端訪問(wèn)native service, 也就是說(shuō),service的訪問(wèn)與語(yǔ)言無(wú)關(guān)。
Android里大部分的跨進(jìn)程的IPC都是基于Binder實(shí)現(xiàn)。
Proxy 通過(guò) Interface 類定義的接口訪問(wèn)Server端代碼。
Service可以分為匿名和具名Service. 前者沒(méi)有注冊(cè)到ServiceManager, 應(yīng)用無(wú)法通過(guò)名字獲取到訪問(wèn)該服務(wù)的Proxy對(duì)象。
Service通常在后臺(tái)線程執(zhí)行(相對(duì)于前臺(tái)的Activity), 但Service不等同于Thread,Service可以運(yùn)行在多個(gè)Thread上,一般這些Thread稱為 Binder Thread.
要了解Service,我們得先從 Binder 入手。
2. Binder
先給一張Binder相關(guān)的類圖一瞰Binder全貌,從上面的類圖(點(diǎn)擊看大圖)跟Binder大致有這么幾部分:
Native 實(shí)現(xiàn): IBinder, BBinder, BpBinder, IPCThread, ProcessState, IInterface, etc
Java 實(shí)現(xiàn): IBinder, Binder, BinderProxy, Stub, Proxy.
Binder Driver: binder_proc, binder_thread, binder_node, etc.
我們將分別對(duì)這三部分進(jìn)行詳細(xì)的分析,首先從中間的Native實(shí)現(xiàn)開(kāi)始。
通常來(lái)說(shuō),接口是分析代碼的入口,Android中'I' 打頭的類統(tǒng)統(tǒng)是接口類(C++里就是抽象類), 自然,分析Binder就得先從IBinder下手。先看看他的定義。
class IBinder : public virtual RefBase{public: ... virtual sp<IInterface> queryLocalInterface(const String16& descriptor); //返回一個(gè)IInterface對(duì)象 ... virtual const String16& getInterfaceDescriptor() const = 0; virtual bool isBinderAlive() const = 0; virtual status_t pingBinder() = 0; virtual status_t dump(int fd, const Vector<String16>& args) = 0; virtual status_t transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) = 0; virtual status_t linkToDeath(const sp<DeathRecipient>& recipient, void* cookie = NULL, uint32_t flags = 0) = 0; virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient, void* cookie = NULL, uint32_t flags = 0, wp<DeathRecipient>* outRecipient = NULL) = 0; ... virtual BBinder* localBinder(); //返回一個(gè)BBinder對(duì)象 virtual BpBinder* remoteBinder(); //返回一個(gè)BpBinder對(duì)象};
有接口必然有實(shí)現(xiàn),從圖中可以看出,BBinder和BpBinder都是IBinder的實(shí)現(xiàn)類,它們干啥用的,有啥區(qū)別?有興趣同學(xué)可以去分別去讀讀他們的代碼,分別在
Bpinder: frameworks/native/lib/binder/BpBinder.cpp
BBinder: frameworks/native/lib/binder/Binder.cpp
這里我們簡(jiǎn)單總結(jié)一下他們的區(qū)別:
接口BBinderBpBinder
queryLocalInterface()沒(méi)有實(shí)現(xiàn), 默認(rèn)實(shí)現(xiàn) IBinder 默認(rèn){reutrn NULL}; 沒(méi)有實(shí)現(xiàn) IBinder 默認(rèn)實(shí)現(xiàn) {return NULL}
getInterfaceDescriptor() {return sEmptyDescriptor;} (this)->transact(INTERFACE_TRANSACTION, send, &reply);
...
mDescriptorCache = res;
isBinderAlive() {return true;}{return mAlive != 0;}
pingBinder(){return NoError;}{transact(PING_TRANSACTION, send, &reply);
linkToDeath(){return INVALID_OPERATION;} {self->requestDeathNotification(mHandle, this);}
unlinkToDeath() {return INVALID_OPERATION;}{self->clearDeathNotification(mHandle, this);}
localBinder(){return this;}沒(méi)有實(shí)現(xiàn), IBinder默認(rèn)實(shí)現(xiàn) {return NULL};
remoteBinder()沒(méi)有實(shí)現(xiàn),IBinder默認(rèn)實(shí)現(xiàn) {return NULL;}{return this};
transact(){err = onTransact(code, data, reply, flags);}IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
onTransact()
switch (code) {
case INTERFACE_TRANSACTION:
reply->writeString16(getInterfaceDescriptor());
return NO_ERROR; ...
沒(méi)有實(shí)現(xiàn)
看出來(lái)了吧,它們的差異在于它們是通信兩端的不同實(shí)現(xiàn),BBinder是服務(wù)端,而B(niǎo)pBinder是客戶端,為什么這么說(shuō)?
pingBinder, BBinder直接返回OK,而B(niǎo)pBinder需要運(yùn)行一個(gè)transact函數(shù),這個(gè)函數(shù)具體做什么,我們后面會(huì)介紹。
linkToDeath()是用來(lái)在服務(wù)掛的時(shí)候通知客戶端的,那服務(wù)端當(dāng)然不需要自己監(jiān)視自己咯,所以BBinder直接返回非法,而B(niǎo)pbinder需要通過(guò)requestDeathNotification()要求某人完成這個(gè)事情,究竟是誰(shuí)提供這個(gè)服務(wù)?答案后面揭曉。
在Android中,remote一般代表某個(gè)遠(yuǎn)端對(duì)象的本地代理,想象一下航空公司和機(jī)票代理,BBinder是航空公司,當(dāng)然沒(méi)有remote的了,那BpBinder就是機(jī)票代理了,所以remote()自然返回自己了。
Transact的英文意思是交易,就是買賣嘛,那自然transact()就是買的操作,而onTransact()就是賣的操作,BBinder的transact()的實(shí)現(xiàn)就是onTransact(), 航空公司的買票當(dāng)然不用通過(guò)機(jī)票代理了,直接找自己人就好了。
所以結(jié)論是,BBinder代表著服務(wù)端,而B(niǎo)pBinder則是它在客戶端的代理,客戶程序通過(guò)BpBinder的transact()發(fā)起請(qǐng)求,而服務(wù)器端的BBinder在onTranscat()里響應(yīng)請(qǐng)求,并將結(jié)果返回。
可是交易肯定有目標(biāo)的吧,回到航空公司和機(jī)票代理的例子,如果要訂去某個(gè)地方的機(jī)票,我們?cè)趺匆驳孟炔樵円幌露加心切┖桨啵缓蟛拍芨嬖V機(jī)票代理訂具體的航班號(hào)吧。這里的查詢和預(yù)訂可以看成服務(wù)的接口函數(shù),而航班號(hào)就是我們傳遞給機(jī)票代理的參數(shù)??蛻舫绦蛲ㄟ^(guò)queryLocalInterface() 可以知道航空公司都提供哪些服務(wù)。
可是奇怪的是BBinder和BpBinder都沒(méi)有實(shí)現(xiàn)這個(gè)接口啊,那肯定另有他人實(shí)現(xiàn)這個(gè)類了,這個(gè)人就是IInterface.h, 看看代碼
template<typename INTERFACE>inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface( const String16& _descriptor){ if (_descriptor == INTERFACE::descriptor) return this; return NULL;}
BnInterface<INTERFACE> 對(duì)象將自己強(qiáng)制轉(zhuǎn)換成 IInterface對(duì)象返回,看看BnInterface的定義:
template<typename INTERFACE>class BnInterface : public INTERFACE, public BBinder{public: virtual sp<IInterface> queryLocalInterface(const String16& _descriptor); virtual const String16& getInterfaceDescriptor() const;protected: virtual IBinder* onAsBinder();};
是一個(gè)模板類,繼承了BBinder, 還有模板 INTERFACE。我們剛才已經(jīng)看過(guò),BBinder沒(méi)有實(shí)現(xiàn)queryLocalInterface(), 而B(niǎo)nInterface 返回自己,可以他并沒(méi)有繼承IInterface, 怎么可以強(qiáng)制轉(zhuǎn)換呢,唯一的解釋就是 INTERFACE模板必須繼承和實(shí)現(xiàn)IInterface.
class IInterface : public virtual RefBase{public: IInterface(); sp<IBinder> asBinder(); sp<const IBinder> asBinder() const; protected: virtual ~IInterface(); virtual IBinder* onAsBinder() = 0;};
這也太簡(jiǎn)單了吧,只是定義了 從Interface 到 IBinder的轉(zhuǎn)換接口 asBinder, 而剛才我們研究的queryLocalInterface() 正好反過(guò)來(lái),說(shuō)明IBinder 和 IInterface 之間是可以互轉(zhuǎn)的,一個(gè)人怎么可以變成另外一個(gè)人呢?唯一的解釋就是這個(gè)人有雙重性格,要么他同時(shí)繼承 IInterface 和 IBinder, 要么他體內(nèi)有這兩個(gè)對(duì)象同時(shí)存在,不賣關(guān)子了,在服務(wù)端,這個(gè)雙重性格的人就是BnXXX, XXX 代表某個(gè)具體的服務(wù),我們以圖中的BnMediaPlayer為例,看看他的定義
class BnMediaPlayer: public BnInterface<IMediaPlayer>{public: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);};class IMediaPlayer: public IInterface{public: DECLARE_META_INTERFACE(MediaPlayer); ...}
這下本性都露出來(lái)了,IBinder 和 IInterface 的影子都露出來(lái)了,讓我們用圖梳理一下 (箭頭代表繼承關(guān)系)
歸納一下,
BBinder 實(shí)現(xiàn)了大部分的IBinder 接口,除了onTransact() 和 queryLocalInterface(), getInterfaceDescriptor();
BnInterface 實(shí)現(xiàn)了IBinder的queryLocalInterface()和getInterfaceDescriptor(), 但是其必須借助實(shí)際的接口類。
BnMediaPlayer只是定義了onTransact(), 沒(méi)有實(shí)現(xiàn)。
onTransact()的具體實(shí)現(xiàn)在Client類。
為什么搞得那么復(fù)雜?Google 是希望通過(guò)這些封裝盡可能減少開(kāi)發(fā)者的工作量,開(kāi)發(fā)一個(gè)native的service 開(kāi)發(fā)者只需要做這么幾件事(上圖中深色部分):
定義一個(gè)接口文件, IXXXService, 繼承IInterface
定義BnXXX(), 繼承 BnInterface<IXXXService)
實(shí)現(xiàn)一個(gè)XXXService類,繼承BnXXX(), 并具體實(shí)現(xiàn)onTransact() 函數(shù)。
那客戶端呢? 我們的目標(biāo)是找到一個(gè)類,它必須同時(shí)擁有IBinder 和 IIterface的特性, 先看看BpBinder 吧
class BpBinder : public IBinder
跟IInterface 沒(méi)有關(guān)系,那一定是別人,看看BpInterface 吧,
template<typename INTERFACE>class BpInterface : public INTERFACE, public BpRefBase{public: BpInterface(const sp<IBinder>& remote);protected: virtual IBinder* onAsBinder();};
我們剛才已經(jīng)知道了,INTERFACE 是 IMediaPlayer, 它繼承了IInterface, IInterface 的對(duì)象找到了, 但跟IBinder 沒(méi)關(guān)系?只剩下BpRefBase 了,
class BpRefBase : public virtual RefBase{protected: ... inline IBinder* remote() { return mRemote; } ...private: ... IBinder* const mRemote; RefBase::weakref_type* mRefs; volatile int32_t mState;};
有了,BpRefBase 里有IBinder 成員變量,看來(lái)在客戶端,沒(méi)有一個(gè)類同時(shí)繼承IBinder 和 IInterface, 但是有一個(gè)類繼承了其一,但包含了另外一個(gè),這種在設(shè)計(jì)模式里成為組合(Composition).
還是不太明白?還是用圖解釋吧,
看明白了?從BpInterface開(kāi)始,通過(guò)BpRefBase 我們可以找到IBinder, 這個(gè)轉(zhuǎn)換就在 asBinder() 的實(shí)現(xiàn)里,看看代碼
sp<IBinder> IInterface::asBinder(){ return this ? onAsBinder() : NULL;}sp<const IBinder> IInterface::asBinder() const{ return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL;}template<typename INTERFACE>inline IBinder* BpInterface<INTERFACE>::onAsBinder(){ return remote();}template<typename INTERFACE>IBinder* BnInterface<INTERFACE>::onAsBinder(){ return this;}
這里印證我們上面兩張圖的正確性,onAsBinder是轉(zhuǎn)換的發(fā)生的地方,服務(wù)端(BnInterface)的實(shí)現(xiàn)直接返回了自己,因?yàn)樗^承了兩者,而客戶端(BpInterface)則需要通過(guò)remote()(返回mRemote 成員變量)獲取,因?yàn)樗约罕旧聿皇荌Binder,
那個(gè)BpRefbase的mRemote是如何被賦值的?看看以下代碼
//frameworks/native/libs/binder/binder.cppBpRefBase::BpRefBase(const sp<IBinder>& o) : mRemote(o.get()), mRefs(NULL), mState(0){ ...}
//frameworks/native/include/binder/iinterface.htemplate<typename INTERFACE>inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote) : BpRefBase(remote){}
//frameworks/av/media/libmedia/IMediaPlayer.cpp
class BpMediaPlayer: public BpInterface<IMediaPlayer>{public: BpMediaPlayer(const sp<IBinder>& impl) : BpInterface<IMediaPlayer>(impl) { } ...}
原來(lái)是從子類一級(jí)一級(jí)注入的,那唯一的問(wèn)題就是在哪里完成這個(gè)注入操作, 馬上搜索"new BpMediaPlayer", 奇怪,竟然沒(méi)有,試試搜索"IMediaPlayer“,發(fā)現(xiàn)了一點(diǎn)線索
//av/media/libmedia/IMediaPlayerService.cpp 70: virtual sp<IMediaPlayer> create( 71: const sp<IMediaPlayerClient>& client, int audioSessionId) { 72 Parcel data, reply; 73: ... 77 remote()->transact(CREATE, data, &reply); 78: return interface_cast<IMediaPlayer>(reply.readStrongBinder()); //reply里讀出IBinder,然后轉(zhuǎn)成IMediaPlayer接口對(duì)象 79 }
這里通過(guò)interface_cast 直接把IBinder 轉(zhuǎn)換成了 IMediaPlayer, interface_cast 到底有什么魔力?
template<typename INTERFACE>inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj){ return INTERFACE::asInterface(obj);}
繼續(xù)跟進(jìn) asInterface, 結(jié)果發(fā)現(xiàn)里以下代碼
#define DECLARE_META_INTERFACE(INTERFACE) static const android::String16 descriptor; static android::sp<I##INTERFACE> asInterface( const android::sp<android::IBinder>& obj); virtual const android::String16& getInterfaceDescriptor() const; I##INTERFACE(); virtual ~I##INTERFACE(); #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; } \
恍然大悟,原來(lái)在DECLARE_META_INTERFACE 這個(gè)宏里定義了asInterface, 在IMPLEMENT_META_INTERFACE 里實(shí)現(xiàn)了它,這里果然有一個(gè)new BpMediaPlayer! 然后把它轉(zhuǎn)換成父父類 IMediaPlayer。
一切都清楚了,用一張圖來(lái)表示
客戶端從遠(yuǎn)端獲取一個(gè)IBinder對(duì)象,接著生成BpMediaPlayer, 將其轉(zhuǎn)成 IMediaPlayer 接口對(duì)象,這是用戶程序看到的對(duì)象,并通過(guò)其調(diào)用接口方法,最終調(diào)到BpBinder的transact()。
問(wèn)題又來(lái)了,這個(gè)transact() 怎么傳遞到服務(wù)端,并最終調(diào)到 onTransact()?
回想一下,onTransact() 是IBinder的接口函數(shù)吧,而且Server的IBinder實(shí)現(xiàn)是BBinder, 那一定有人通過(guò)某種方式得到了BBinder對(duì)象。
這個(gè)人就是Binder Driver. 為了找到真相,必須用源頭開(kāi)始,那就是transact()
status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ ... status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); ... return DEAD_OBJECT;}
IPCThreadState的transact()函數(shù)相比IBinder 多了一個(gè)mHandle, 啥來(lái)歷?
BpBinder::BpBinder(int32_t handle) : mHandle(handle)
構(gòu)造帶進(jìn)來(lái)的,趕緊找“new BpBinder", 結(jié)果在ProcessState.cpp 看到了
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){ ... IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { b = new BpBinder(handle);
找誰(shuí)call了getStrongProxyForHandle?為了快速找到調(diào)用棧,我們?cè)贐pBinder的構(gòu)造函數(shù)里加了這么幾句話:
#include <utils/CallStack.h>...CallStack cs;cs.update();cs.dump("BpBinder")
然后得到了下面的打印
09-29 07:11:14.363 1624 1700 D BpBinder: #00 pc 0001eb34 /system/lib/libbinder.so (android::BpBinder::BpBinder(int)+260)09-29 07:11:14.363 1624 1700 D BpBinder: #01 pc 0003b9a2 /system/lib/libbinder.so (android::ProcessState::getStrongProxyForHandle(int)+226)09-29 07:11:14.363 1624 1700 D BpBinder: #02 pc 00032b8c /system/lib/libbinder.so (android::Parcel::readStrongBinder() const+316) //frameworks/native/libs/binder/Parcel.cpp:24709-29 07:11:14.363 1624 1700 D BpBinder: #03 pc 000ad9d2 /system/lib/libandroid_runtime.so //frameworks/base/core/jni/android_os_Parcel.cpp:35509-29 07:11:14.363 1624 1700 D BpBinder: #04 pc 00029c5b /system/lib/libdvm.so (dvmPlatformInvoke+79) //dalvik/vm/arch/x86/Call386ABI.S:128
#04 dvmPlatformInvork 說(shuō)明這是一個(gè)Jni調(diào)用,#03 對(duì)應(yīng)的代碼是
return javaObjectForIBinder(env, parcel->readStrongBinder());
應(yīng)該是Java傳下來(lái)一個(gè)Parcel對(duì)象,然后由本地代碼進(jìn)行解析,從中讀出IBinder對(duì)象,并最終返回。也就是說(shuō),遠(yuǎn)端有人將這個(gè)IBinder對(duì)象封在Parcel里。還是沒(méi)有頭緒?繼續(xù)順著調(diào)用棧往前看,
#02 對(duì)應(yīng)于下面的代碼
status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out){ const flat_binder_object* flat = in.readObject(false); ...case BINDER_TYPE_HANDLE: *out = proc->getStrongProxyForHandle(flat->handle); return finish_unflatten_binder( static_cast<BpBinder*>(out->get()), *flat, in); } } return BAD_TYPE;}
#bionic/libc/kernel/common/linux/binder.h
struct flat_binder_object { unsigned long type; unsigned long flags; union { void *binder; signed long handle; }; void *cookie;};
原來(lái)mHandle就是flat_binder_object里面的handle, 它只是一個(gè)數(shù)字!這個(gè)數(shù)據(jù)結(jié)構(gòu)定義在Kernel里,是經(jīng)過(guò)Kernel轉(zhuǎn)手的。越來(lái)越亂了,趕緊整理一下思路:
1. Kernel 封裝了一個(gè)數(shù)據(jù)結(jié)構(gòu)(flat_binder_object),里面帶有一個(gè)數(shù)字(mHandle)。
2. 客戶端獲取這個(gè)數(shù)字后,生成一個(gè)BpBinder的對(duì)象。
3. 然后當(dāng)客戶端需要訪問(wèn)遠(yuǎn)端服務(wù)的時(shí)候,將這個(gè)數(shù)字附上。
回到現(xiàn)實(shí)生活,機(jī)票代理需要向航空公司查詢或訂票的話,一定要知道是哪個(gè)航空公司,莫非這個(gè)號(hào)就是航空公司的編號(hào)?
恭喜你,就是那么簡(jiǎn)單,這個(gè)號(hào)就對(duì)應(yīng)了服務(wù)器端的提供的某一個(gè)服務(wù),Android 中每個(gè)Service都有一個(gè)號(hào)碼(根據(jù)創(chuàng)建時(shí)間遞增,0號(hào)Service 是ServiceManager,讓我用下面的圖來(lái)描述整個(gè)過(guò)程吧,
1. 在已知服務(wù)名的情況下,App 通過(guò)getService() 從ServiceManager 獲取該服務(wù)的信息,該信息封裝在Parcel里。
2. 應(yīng)用程序收到返回的這個(gè)Parcel對(duì)象(通過(guò)Kernel), 從中讀取出flat_binder_object 對(duì)象,最終從對(duì)象中得到服務(wù)對(duì)應(yīng)的服務(wù)號(hào),mHandle.
3. 以該號(hào)碼作為參數(shù)輸入生成一個(gè)IBinder對(duì)象(實(shí)際是BpBinder)。
4. 應(yīng)用獲取該對(duì)象后,通過(guò)asInterface(IBinder*) 生成服務(wù)對(duì)應(yīng)的Proxy對(duì)象(BpXXX),并將其強(qiáng)轉(zhuǎn)為接口對(duì)象(IXXX),然后直接調(diào)用接口函數(shù)。
5. 所有的接口對(duì)象調(diào)用最終會(huì)走到BpBinder->transact()函數(shù),這個(gè)函數(shù)調(diào)用IPCThreadState->transact()并以Service號(hào)作為參數(shù)之一。
6. 最終通過(guò)系統(tǒng)調(diào)用ioctrl() 進(jìn)入內(nèi)核空間,Binder驅(qū)動(dòng)根據(jù)傳進(jìn)來(lái)的Service 號(hào)尋找該Service正處于等待狀態(tài)的Binder Thread, 喚醒它并在該線程內(nèi)執(zhí)行相應(yīng)的函數(shù),并返回結(jié)果給APP。
強(qiáng)調(diào)一下:
1. 從應(yīng)用程序的角度來(lái)看,他只認(rèn)識(shí)IBinder 和 IMediaPlayer 這兩個(gè)類,但真正的實(shí)現(xiàn)在BpBinder 和 BpMediaPlayer, 這正是設(shè)計(jì)模式所推崇的“ Programs to interface, not implementations", 可以說(shuō)Android 是一個(gè)嚴(yán)格遵循設(shè)計(jì)模式思想精心設(shè)計(jì)的系統(tǒng),我們將來(lái)會(huì)就這個(gè)話題進(jìn)行深入的探討。
2. 客戶端應(yīng)該層層的封裝,最終的目的就是獲取和傳遞這個(gè)mHandle 值,從圖中,我們看到,這個(gè)mHandle至來(lái)自與IServiceManager, 他是一個(gè)管理其他服務(wù)的服務(wù),通過(guò)服務(wù)的名字我們可以拿到這個(gè)服務(wù)對(duì)應(yīng)的Handle號(hào),類似網(wǎng)絡(luò)域名服務(wù)系統(tǒng)。但是我們說(shuō)了,IServiceManager也是服務(wù)啊,要訪問(wèn)他我們也需要一個(gè)Handle號(hào)啊,對(duì)了,就如同你必須為你的機(jī)器設(shè)置DNS 服務(wù)器地址,你才能獲得DNS 服務(wù)。在Android系統(tǒng)里, 默認(rèn)的將ServiceManger的Handler號(hào)設(shè)為0,0就是DNS服務(wù)器的地址,這樣,我們通過(guò)調(diào)用 getStrongProxyForHandle(0) 就可以拿到ServiceManager 的IBinder 對(duì)象,當(dāng)然,系統(tǒng)提供一個(gè) getService(char *)函數(shù)來(lái)幫助完成這個(gè)過(guò)程。
3. Android Binder 的設(shè)計(jì)目標(biāo)就是讓訪問(wèn)遠(yuǎn)端服務(wù)就像調(diào)用本地函數(shù)一樣簡(jiǎn)單,但是遠(yuǎn)端的對(duì)象不在本地控制之內(nèi),我們必須保證調(diào)用過(guò)程中遠(yuǎn)端的對(duì)象不能被析構(gòu),否則本地應(yīng)用程序?qū)⒑苡锌赡鼙罎?。同時(shí),萬(wàn)一遠(yuǎn)端服務(wù)異常退出,如Crash, 本地對(duì)象必須知曉從而避免后續(xù)的錯(cuò)誤。Android 通過(guò) 智能指針 和 DeathNotification 來(lái)支持這兩個(gè)要求,我們會(huì)有專門的章節(jié)介紹智能指針,這里我們會(huì)在后面簡(jiǎn)單介紹 DeathNotifycation的實(shí)現(xiàn)原理。
Binder的上層設(shè)計(jì)邏輯簡(jiǎn)單介紹完畢。我們接下來(lái)看看Binder的底層設(shè)計(jì)。
3. Binder Driver
我們知道,Linux的進(jìn)程空間相互獨(dú)立,兩個(gè)進(jìn)程只能通過(guò)Kernel space 進(jìn)行互訪,所有的IPC 機(jī)制,最底層的實(shí)現(xiàn)都是在Kernel space. Binder 也是如此,通過(guò)系統(tǒng)調(diào)用切入內(nèi)核態(tài),內(nèi)核尋找到提供服務(wù)的進(jìn)程,喚醒他并進(jìn)入用戶空間,然后在某個(gè)線程里調(diào)用onTransact(), 完成特定操作,并將結(jié)果返回到應(yīng)用程序。那Binder Driver是如何搭起連接服務(wù)端和客戶端的這座橋梁呢?
先看看binder driver 內(nèi)部的數(shù)據(jù)結(jié)構(gòu)吧:
下面一一進(jìn)行解釋:
1. Binder node:
我們前面說(shuō)過(guò)Service 其實(shí)是一個(gè)存在于某個(gè)進(jìn)程里的對(duì)象,因此,進(jìn)程PID 和 對(duì)象地址可以唯一的標(biāo)識(shí)一個(gè)Service 對(duì)象,除此之外,因?yàn)檫@個(gè)對(duì)象可能被很多應(yīng)用所使用,必須有引用計(jì)數(shù)來(lái)管理他的生命周期。這些工作都必須在內(nèi)核里完成,Binder node 就是這樣一個(gè)結(jié)構(gòu)體來(lái)管理每個(gè)Service 對(duì)象。
struct binder_node { int debug_id; //kernel內(nèi)部標(biāo)識(shí)node的id struct binder_work work; union { struct rb_node rb_node; struct hlist_node dead_node; }; struct binder_proc *proc; //Service所在進(jìn)程的結(jié)構(gòu)體 struct hlist_head refs; //雙向鏈表頭,鏈表里存放一系列指針,指向引用該Service的binder_ref對(duì)象, int internal_strong_refs; //內(nèi)部強(qiáng)引用計(jì)數(shù) int local_weak_refs; //弱引用計(jì)數(shù) int local_strong_refs; //強(qiáng)引用計(jì)數(shù) binder_ptr __user ptr; //Service對(duì)象地址 binder_ptr __user cookie; unsigned has_strong_ref:1; unsigned pending_strong_ref:1; unsigned has_weak_ref:1; unsigned pending_weak_ref:1; unsigned has_async_transaction:1; unsigned accept_fds:1; unsigned min_priority:8; struct list_head async_todo;};
2. binder_ref
binder_ref 描述了每個(gè)對(duì)服務(wù)對(duì)象的引用,對(duì)應(yīng)與Client端。如上圖所示,每個(gè)Ref通過(guò)node指向binder_node. 一個(gè)進(jìn)程所有的binder_ref通過(guò)兩個(gè)紅黑樹(shù)(RbTree)進(jìn)行管理,通過(guò)binder_get_ref() 和 binder_get_ref_for_node快速查找。
struct binder_ref { /* Lookups needed: */ /* node + proc => ref (transaction) */ /* desc + proc => ref (transaction, inc/dec ref) */ /* node => refs + procs (proc exit) */ int debug_id; struct rb_node rb_node_desc; struct rb_node rb_node_node; struct hlist_node node_entry; struct binder_proc *proc; //應(yīng)用進(jìn)程 struct binder_node *node; uint32_t desc; int strong; int weak; struct binder_ref_death *death; //如果不為空,則client想獲知binder的死亡};
3. binder_proc
一個(gè)進(jìn)程既包含的Service對(duì)象,也可能包含對(duì)其他Service對(duì)象的引用. 如果作為Service對(duì)象進(jìn)程,它可能會(huì)存在多個(gè)Binder_Thread。這些信息都在binder_proc結(jié)構(gòu)體進(jìn)行管理。
struct binder_proc { struct hlist_node proc_node; //全局鏈表 binder_procs 的node之一 struct rb_root threads; //binder_thread紅黑樹(shù),存放指針,指向進(jìn)程所有的binder_thread, 用于Server端 struct rb_root nodes; //binder_node紅黑樹(shù),存放指針,指向進(jìn)程所有的binder 對(duì)象 struct rb_root refs_by_desc; //binder_ref 紅黑樹(shù),根據(jù)desc(service No) 查找對(duì)應(yīng)的引用 struct rb_root refs_by_node; //binder_ref 紅黑樹(shù),根據(jù)binder_node 指針查找對(duì)應(yīng)的引用 int pid; struct vm_area_struct *vma; struct mm_struct *vma_vm_mm; struct task_struct *tsk; struct files_struct *files; struct hlist_node deferred_work_node; int deferred_work; void *buffer; ptrdiff_t user_buffer_offset; struct list_head buffers; struct rb_root free_buffers; struct rb_root allocated_buffers; size_t free_async_space; struct page **pages; size_t buffer_size; uint32_t buffer_free; struct list_head todo; //task_list, binder_work鏈表,存放指針最終指向某個(gè)binder_transaction對(duì)象 wait_queue_head_t wait; struct binder_stats stats; struct list_head delivered_death; int max_threads; int requested_threads; int requested_threads_started; int ready_threads; long default_priority; struct dentry *debugfs_entry;};
為了實(shí)現(xiàn)快速的查找,binder_proc內(nèi)部維護(hù)了若干個(gè)數(shù)據(jù)結(jié)構(gòu),如圖中黃色高亮所示,
4. binder_transaction
每個(gè)transact() 調(diào)用在內(nèi)核里都會(huì)生產(chǎn)一個(gè)binder_transaction 對(duì)象,這個(gè)對(duì)象會(huì)最終送到Service進(jìn)程或線程的todo隊(duì)列里,然后喚醒他們來(lái)最終完成onTransact()調(diào)用。
struct binder_transaction { int debug_id; //一個(gè)全局唯一的ID struct binder_work work; // 用于存放在todo鏈表里 struct binder_thread *from; //transaction 發(fā)起的線程。如果BC_TRANSACTION, 則為客戶端線程,如果是BC_REPLY, 則為服務(wù)端線程。 struct binder_transaction *from_parent; //上一個(gè)binder_transaction. 用于client端 struct binder_proc *to_proc; //目標(biāo)進(jìn)程 struct binder_thread *to_thread; //目標(biāo)線程 struct binder_transaction *to_parent; //上一個(gè)binder_transaction, 用于server端 unsigned need_reply:1; /* unsigned is_dead:1; */ /* not used at the moment */ struct binder_buffer *buffer; unsigned int code; unsigned int flags; long priority; long saved_priority; kuid_t sender_euid;};
5. binder_thread
binder_proc里的threads 紅黑樹(shù)存放著指向binder_thread對(duì)象的指針。這里的binder_thread 不僅僅包括service的binder thread, 也包括訪問(wèn)其他service的調(diào)用thread. 也就是說(shuō)所有與binder相關(guān)的線程都會(huì)在binder_proc的threads紅黑樹(shù)里留下記錄。binder_thread里最重要的兩個(gè)成員變量是 transaction_stack 和 wait.
struct binder_thread { struct binder_proc *proc; struct rb_node rb_node; //紅黑樹(shù)節(jié)點(diǎn) int pid; int looper; // struct binder_transaction *transaction_stack; //transaction棧 struct list_head todo; uint32_t return_error; uint32_t return_error2; wait_queue_head_t wait; //等待隊(duì)列,用于阻塞等待 struct binder_stats stats;};
在binder_proc里面我們也能看到一個(gè)wait 隊(duì)列,是不是意味著線程既可以在proc->wait上等待,也可以在thread->wait上等待?binder driver 對(duì)此有明確的用法,所有的binder threads (server 端)都等待在proc->wait上。因?yàn)閷?duì)于服務(wù)端來(lái)說(shuō),用哪個(gè)thread來(lái)響應(yīng)遠(yuǎn)程調(diào)用請(qǐng)求都是一樣的。然而所有的ref thread(client端)的返回等待都發(fā)生在調(diào)用thread的wait 隊(duì)列,因?yàn)?,?dāng)某個(gè)binder thread 完成服務(wù)請(qǐng)求后,他必須喚醒特定的等待返回的線程。但是有一個(gè)例外,在雙向調(diào)用的情況下,某個(gè)Server端的thread將會(huì)掛在thread->wait上等待,而不是proc->wait. 舉個(gè)例子,假設(shè)兩個(gè)進(jìn)程P1 和 P2,各自運(yùn)行了一個(gè)Service, S1,S2, P1 在 thread T1 里調(diào)用S2提供的服務(wù),然后在T1->wait里等待返回。S2的服務(wù)在P2的binder thread(T2)里執(zhí)行,執(zhí)行過(guò)程中,S2又調(diào)到S1里的某個(gè)接口,按理S1 將在P1的binder thread T3里執(zhí)行, 如果P1接下來(lái)又調(diào)到了P2,那又會(huì)產(chǎn)生新的進(jìn)程 T4, 如果這個(gè)反復(fù)調(diào)用棧很深,需要耗費(fèi)大量的線程,顯然這是非常不高效的設(shè)計(jì)。所以,binder driver 里做了特殊的處理。當(dāng)T2 調(diào)用 S1的接口函數(shù)時(shí),binder driver 會(huì)遍歷T2的transaction_stack, 如果發(fā)現(xiàn)這是一個(gè)雙向調(diào)用(binder_transaction->from->proc 等于P1), 便會(huì)喚醒正在等待reply的T1,T1 完成這個(gè)請(qǐng)求后,繼續(xù)等待S2的回復(fù)。這樣,只需要最多兩個(gè)Thread就可以完成多層的雙向調(diào)用。
binder_thread里的transaction_stack 是用鏈表實(shí)現(xiàn)的堆棧, 調(diào)用線程和服務(wù)線程的transaction有著不同的堆棧。下圖是上面這個(gè)例子的堆棧情形:
6. binder_ref_death
binder_ref 記錄了從client進(jìn)程到server進(jìn)程某個(gè)service的引用,binder_ref_death 是binder_ref的一個(gè)成員變量,它的不為空說(shuō)明了client進(jìn)程想得到這個(gè)service的死亡通知(嚴(yán)格意義上講,是service所在進(jìn)程的死亡通知,因?yàn)橐粋€(gè)進(jìn)程一個(gè)/dev/binder的fd, 只有進(jìn)程死亡了,driver才會(huì)知曉,通過(guò) file_operations->release 接口)。
struct binder_ref_death { struct binder_work work; binder_ptr __user cookie;};
我們可以下面一張時(shí)序圖來(lái)了解binder death notifycation 的全過(guò)程。
7. binder_work
從應(yīng)用程序角度來(lái)看,所有的binder調(diào)用都是同步的。但在binder driver 內(nèi)部,兩個(gè)進(jìn)程間的交互都是異步的,一個(gè)進(jìn)程產(chǎn)生的請(qǐng)求會(huì)變成一個(gè)binder_work, 并送入目標(biāo)進(jìn)程或線程的todo 隊(duì)列里,然后喚醒目標(biāo)進(jìn)程和線程來(lái)完成這個(gè)請(qǐng)求,并阻塞等待結(jié)果。binder_work的定義如下:
struct binder_work { struct list_head entry; enum { BINDER_WORK_TRANSACTION = 1, BINDER_WORK_TRANSACTION_COMPLETE, BINDER_WORK_NODE, BINDER_WORK_DEAD_BINDER, BINDER_WORK_DEAD_BINDER_AND_CLEAR, BINDER_WORK_CLEAR_DEATH_NOTIFICATION, } type;};
很簡(jiǎn)單,其實(shí)只定義了一個(gè)鏈表的節(jié)點(diǎn)和work的類型。
8. binder_buffer
進(jìn)程間通信除了命令,還有參數(shù)和返回值的交換,要將數(shù)據(jù)從一個(gè)進(jìn)程的地址空間,傳到另外一個(gè)進(jìn)程的地址空間,通常需要兩次拷貝,進(jìn)程A -> 內(nèi)核 -> 進(jìn)程B。binder_buffer 就是內(nèi)核里存放交換數(shù)據(jù)的空間(這些數(shù)據(jù)是以Parcel的形式存在)。為了提高效率,Android 的 binder 只需要一次拷貝,因?yàn)閎inder 進(jìn)程通過(guò)mmap將內(nèi)核空間地址映射到用戶空間,從而可以直接訪問(wèn)binder_buffer的內(nèi)容而無(wú)需一次額外拷貝。binder_buffer由內(nèi)核在每次發(fā)起的binder調(diào)用創(chuàng)建,并賦給binder_transaction->buffer. binder driver 根據(jù)binder_transaction 生產(chǎn) transaction_data(包含buffer的指針而非內(nèi)容), 并將其復(fù)制到用戶空間。
9. flat_binder_obj
前面我們說(shuō)過(guò),<proc, handle> 可以標(biāo)識(shí)一個(gè)BpBinder 對(duì)象,而<proc, ptr> 可以標(biāo)識(shí)一個(gè)BBinder對(duì)象。Binder Driver 會(huì)收到來(lái)自與BpBinder 和 BBinder的系統(tǒng)調(diào)用,它是如何判別它們的身份呢?答案就在flat_binder_obj里,先看看它的定義,
struct flat_binder_object { unsigned long type; //見(jiàn)下面定義 unsigned long flags; union { void *binder; //BBinder,通過(guò)它driver可以找到對(duì)應(yīng)的node signed long handle; //BpBinder,根據(jù)它driver可以找到對(duì)應(yīng)的ref }; void *cookie;};enum { BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),};
union表明了在Server端和Client端它有著不同的解讀。type則表明了它的身份。binder driver 根據(jù)它可以找到BpBinder 和 BBinder 在內(nèi)核中相對(duì)應(yīng)的對(duì)象 (ref 或 node). flat_binder_obj 封裝在parcel里,詳見(jiàn)Parcel.cpp.
至此,binder driver里面重要的數(shù)據(jù)結(jié)構(gòu)都介紹完了,大家對(duì)binder driver的工作原理也有了大致的了解,這里再稍作總結(jié):
1. 當(dāng)一個(gè)service向binder driver 注冊(cè)時(shí)(通過(guò)flat_binder_object), driver 會(huì)創(chuàng)建一個(gè)binder_node, 并掛載到該service所在進(jìn)程的nodes紅黑樹(shù)。
2. 這個(gè)service的binder線程在proc->wait 隊(duì)列上進(jìn)入睡眠等待。等待一個(gè)binder_work的到來(lái)。
3. 客戶端的BpBinder 創(chuàng)建的時(shí)候,它在driver內(nèi)部也產(chǎn)生了一個(gè)binder_ref對(duì)象,并指向某個(gè)binder_node, 在driver內(nèi)部,將client和server關(guān)聯(lián)起來(lái)。如果它需要或者Service的死亡狀態(tài),則會(huì)生成相應(yīng)的binfer_ref_death.
4. 客戶端通過(guò)transact() (對(duì)應(yīng)內(nèi)核命令BC_TRANSACTION)請(qǐng)求遠(yuǎn)端服務(wù),driver通過(guò)ref->node的映射,找到service所在進(jìn)程,生產(chǎn)一個(gè)binder_buffer, binder_transaction 和 binder_work 并插入proc->todo隊(duì)列,接著喚醒某個(gè)睡在proc->wait隊(duì)列上的Binder_thread. 與此同時(shí),該客戶端線程在其線程的wait隊(duì)列上進(jìn)入睡眠,等待返回值。
5. 這個(gè)binder thread 從proc->todo 隊(duì)列中讀出一個(gè)binder_transaction, 封裝成transaction_data (命令為 BR_TRANSACTION) 并送到用戶空間。Binder用戶線程喚醒并最終執(zhí)行對(duì)應(yīng)的on_transact() 函數(shù)。
6. Binder用戶線程通過(guò)transact() 向內(nèi)核發(fā)送 BC_REPLY命令,driver收到后從其thread->transaction_stack中找到對(duì)應(yīng)的binder_transaction, 從而知道是哪個(gè)客戶端線程正在等待這個(gè)返回。
7. Driver 生產(chǎn)新的binder_transaction (命令 BR_REPLY), binder_buffer, binder_work, 將其插入應(yīng)用線程的todo對(duì)立,并將該線程喚醒。
8. 客戶端的用戶線程收到回復(fù)數(shù)據(jù),該Transaction完成。
9. 當(dāng)service所在進(jìn)程發(fā)生異常退出,driver 的 release函數(shù)被調(diào)到,在某位內(nèi)核work_queue 線程里完成該service在內(nèi)核態(tài)的清理工作(thread,buffer,node,work...), 并找到所有引用它的binder_ref, 如果某個(gè)binder_ref 有不為空的binder_ref_death, 生成新的binder_work, 送人其線程的todo 對(duì)立,喚醒它來(lái)執(zhí)行剩余工作,用戶端的DeathRecipient 會(huì)最終被調(diào)用來(lái)完成client端的清理工作。
下面這張時(shí)序圖描述了上述一個(gè)transaction完成的過(guò)程。不同的顏色代表不同的線程。注意的是,雖然Kernel和User space 線程的顏色是不一樣的,但所有的系統(tǒng)調(diào)用都發(fā)生在用戶進(jìn)程的上下文里(所謂上下文,就是Kernel能通過(guò)某種方式找到關(guān)聯(lián)的進(jìn)程(通過(guò)Kernel的current 宏),并完成進(jìn)程相關(guān)的操作,比如說(shuō)喚醒某個(gè)睡眠的線程,或跟用戶空間交換數(shù)據(jù),copy_from, copy_to, 與之相對(duì)應(yīng)的是中斷上下文,其完全異步觸發(fā),因此無(wú)法做任何與進(jìn)程相關(guān)的操作,比如說(shuō)睡眠,鎖等)。
4. Java Binder
Binder 的學(xué)習(xí)已經(jīng)接近尾聲了,我們已經(jīng)研究了Binder Driver, C/C++的實(shí)現(xiàn),就差最后一個(gè)部分了,Binder在Java端的實(shí)現(xiàn)了。Java端的實(shí)現(xiàn)與Native端類似,我們用下面的表格和類圖概括他們的關(guān)系
NativeJavaNote
IBinderIBinder
IInterfaceIInterface
IXXXIXXXaidl文件定義
BBinderBinder 通過(guò)JavaBBinder類作為橋梁
BpBinderBinderProxy 通過(guò)JNI訪問(wèn)Native的實(shí)現(xiàn)
BnInterfaceN/A
BpInterface N/A
BnXXXStubaidl工具自動(dòng)生成
BpXXX Proxyaidl工具自動(dòng)生成
可見(jiàn),Java較Native端實(shí)現(xiàn)簡(jiǎn)單很多,通過(guò)Aidl工具來(lái)實(shí)現(xiàn)類似功能。所以,要實(shí)現(xiàn)一個(gè)Java端的service,只需要做以下幾件事情:
1. 寫一個(gè).aidl文件,里面用AIDL語(yǔ)言定義一個(gè)接口類IXXX。
2.在Android.mk里加入該文件,這樣編譯系統(tǒng)會(huì)自動(dòng)生成一個(gè)IXXX.java, 放在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core 下面。
3. 在服務(wù)端,寫一個(gè)類,擴(kuò)展IXXX.Stub,具體實(shí)現(xiàn)IXXX的接口函數(shù)。