在 Zygote啓動過程 一文中咱們說道,Zygote一輩子中最重要的一件事就是生下了 System Server 這個大兒子,System Server 擔負着提供系統 Service的重任,在深刻了解這些Service 以前,咱們首先要了解 什麼是Service?它的工做原理是什麼?html
簡單來講,Service就是提供服務的代碼,這些代碼最終體現爲一個個的接口函數,因此,Service就是實現一組函數的對象,一般也稱爲組件。Android 的Service 有如下一些特色:java
要了解Service,咱們得先從 Binder 入手。node
先給一張Binder相關的類圖一瞰Binder全貌,從上面的類圖(點擊看大圖)跟Binder大體有這麼幾部分:linux
Native 實現: IBinder, BBinder, BpBinder, IPCThread, ProcessState, IInterface, etcandroid
Java 實現: IBinder, Binder, BinderProxy, Stub, Proxy.設計模式
Binder Driver: binder_proc, binder_thread, binder_node, etc.服務器
咱們將分別對這三部分進行詳細的分析,首先從中間的Native實現開始。cookie
一般來講,接口是分析代碼的入口,Android中'I' 打頭的類通通是接口類(C++裏就是抽象類), 天然,分析Binder就得先從IBinder下手。先看看他的定義。網絡
class IBinder : public virtual RefBase { public: ... virtual sp<IInterface> queryLocalInterface(const String16& descriptor); //返回一個IInterface對象 ... 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(); //返回一個BBinder對象 virtual BpBinder* remoteBinder(); //返回一個BpBinder對象 };
有接口必然有實現,從圖中能夠看出,BBinder和BpBinder都是IBinder的實現類,它們幹啥用的,有啥區別?有興趣同窗能夠去分別去讀讀他們的代碼,分別在數據結構
這裏咱們簡單總結一下他們的區別:
接口 | BBinder | BpBinder |
queryLocalInterface() | 沒有實現, 默認實現 IBinder 默認{reutrn NULL}; | 沒有實現 IBinder 默認實現 {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;} | 沒有實現, IBinder默認實現 {return NULL}; |
remoteBinder() | 沒有實現,IBinder默認實現 {return NULL;} | {return this}; |
transact() | {err = onTransact(code, data, reply, flags);} | IPCThreadState::self()->transact(mHandle, code, data, reply, flags); |
onTransact() | switch (code) { |
沒有實現 |
看出來了吧,它們的差別在於它們是通訊兩端的不一樣實現,BBinder是服務端,而BpBinder是客戶端,爲何這麼說?
因此結論是,BBinder表明着服務端,而BpBinder則是它在客戶端的代理,客戶程序經過BpBinder的transact()發起請求,而服務器端的BBinder在onTranscat()裏響應請求,並將結果返回。
但是交易確定有目標的吧,回到航空公司和機票代理的例子,若是要訂去某個地方的機票,咱們怎麼也得先查詢一下都有那些航班,而後才能告訴機票代理訂具體的航班號吧。這裏的查詢和預訂能夠當作服務的接口函數,而航班號就是咱們傳遞給機票代理的參數。客戶程序經過queryLocalInterface() 能夠知道航空公司都提供哪些服務。
但是奇怪的是BBinder和BpBinder都沒有實現這個接口啊,那確定另有他人實現這個類了,這我的就是IInterface.h, 看看代碼
template<typename INTERFACE> inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface( const String16& _descriptor) { if (_descriptor == INTERFACE::descriptor) return this; return NULL; }
BnInterface<INTERFACE> 對象將本身強制轉換成 IInterface對象返回,看看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(); };
是一個模板類,繼承了BBinder, 還有模板 INTERFACE。咱們剛纔已經看過,BBinder沒有實現queryLocalInterface(), 而BnInterface 返回本身,能夠他並無繼承IInterface, 怎麼能夠強制轉換呢,惟一的解釋就是 INTERFACE模板必須繼承和實現IInterface.
class IInterface : public virtual RefBase { public: IInterface(); sp<IBinder> asBinder(); sp<const IBinder> asBinder() const; protected: virtual ~IInterface(); virtual IBinder* onAsBinder() = 0; };
這也太簡單了吧,只是定義了 從Interface 到 IBinder的轉換接口 asBinder, 而剛纔咱們研究的queryLocalInterface() 正好反過來,說明IBinder 和 IInterface 之間是能夠互轉的,一我的怎麼能夠變成另一我的呢?惟一的解釋就是這我的有雙重性格,要麼他同時繼承 IInterface 和 IBinder, 要麼他體內有這兩個對象同時存在,不賣關子了,在服務端,這個雙重性格的人就是BnXXX, XXX 表明某個具體的服務,咱們以圖中的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); ... }
這下本性都露出來了,IBinder 和 IInterface 的影子都露出來了,讓咱們用圖梳理一下 (箭頭表明繼承關係)
概括一下,
爲何搞得那麼複雜?Google 是但願經過這些封裝儘量減小開發者的工做量,開發一個native的service 開發者只須要作這麼幾件事(上圖中深色部分):
那客戶端呢? 咱們的目標是找到一個類,它必須同時擁有IBinder 和 IIterface的特性, 先看看BpBinder 吧
class BpBinder : public IBinder
跟IInterface 沒有關係,那必定是別人,看看BpInterface 吧,
template<typename INTERFACE> class BpInterface : public INTERFACE, public BpRefBase { public: BpInterface(const sp<IBinder>& remote); protected: virtual IBinder* onAsBinder(); };
咱們剛纔已經知道了,INTERFACE 是 IMediaPlayer, 它繼承了IInterface, IInterface 的對象找到了, 但跟IBinder 不要緊?只剩下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 成員變量,看來在客戶端,沒有一個類同時繼承IBinder 和 IInterface, 可是有一個類繼承了其一,但包含了另一個,這種在設計模式裏成爲組合(Composition).
仍是不太明白?仍是用圖解釋吧,
看明白了?從BpInterface開始,經過BpRefBase 咱們能夠找到IBinder, 這個轉換就在 asBinder() 的實現裏,看看代碼
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是轉換的發生的地方,服務端(BnInterface)的實現直接返回了本身,由於它繼承了二者,而客戶端(BpInterface)則須要經過remote()(返回mRemote 成員變量)獲取,由於他本身自己不是IBinder,
那個BpRefbase的mRemote是如何被賦值的?看看如下代碼
//frameworks/native/libs/binder/binder.cpp BpRefBase::BpRefBase(const sp<IBinder>& o) : mRemote(o.get()), mRefs(NULL), mState(0) { ... }
//frameworks/native/include/binder/iinterface.h template<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) { } ... }
原來是從子類一級一級注入的,那惟一的問題就是在哪裏完成這個注入操做, 立刻搜索"new BpMediaPlayer", 奇怪,居然沒有,試試搜索"IMediaPlayer「,發現了一點線索
//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,而後轉成IMediaPlayer接口對象 79 }
這裏經過interface_cast 直接把IBinder 轉換成了 IMediaPlayer, interface_cast 到底有什麼魔力?
template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); }
繼續跟進 asInterface, 結果發現裏如下代碼
#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; \ } \
恍然大悟,原來在DECLARE_META_INTERFACE 這個宏裏定義了asInterface, 在IMPLEMENT_META_INTERFACE 裏實現了它,這裏果真有一個new BpMediaPlayer! 而後把它轉換成父父類 IMediaPlayer。
一切都清楚了,用一張圖來表示
客戶端從遠端獲取一個IBinder對象,接着生成BpMediaPlayer, 將其轉成 IMediaPlayer 接口對象,這是用戶程序看到的對象,並經過其調用接口方法,最終調到BpBinder的transact()。
問題又來了,這個transact() 怎麼傳遞到服務端,並最終調到 onTransact()?
回想一下,onTransact() 是IBinder的接口函數吧,並且Server的IBinder實現是BBinder, 那必定有人經過某種方式獲得了BBinder對象。
這我的就是Binder Driver. 爲了找到真相,必須用源頭開始,那就是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()函數相比IBinder 多了一個mHandle, 啥來歷?
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
構造帶進來的,趕忙找「new BpBinder", 結果在ProcessState.cpp 看到了
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { ... IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { b = new BpBinder(handle);
找誰call了getStrongProxyForHandle?爲了快速找到調用棧,咱們在BpBinder的構造函數里加了這麼幾句話:
#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:247 09-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:355 09-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 說明這是一個Jni調用,#03 對應的代碼是
return javaObjectForIBinder(env, parcel->readStrongBinder());
應該是Java傳下來一個Parcel對象,而後由本地代碼進行解析,從中讀出IBinder對象,並最終返回。也就是說,遠端有人將這個IBinder對象封在Parcel裏。仍是沒有頭緒?繼續順着調用棧往前看,
#02 對應於下面的代碼
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; };
原來mHandle就是flat_binder_object裏面的handle, 它只是一個數字!這個數據結構定義在Kernel裏,是通過Kernel轉手的。愈來愈亂了,趕忙整理一下思路:
1. Kernel 封裝了一個數據結構(flat_binder_object),裏面帶有一個數字(mHandle)。
2. 客戶端獲取這個數字後,生成一個BpBinder的對象。
3. 而後當客戶端須要訪問遠端服務的時候,將這個數字附上。
回到現實生活,機票代理須要向航空公司查詢或訂票的話,必定要知道是哪一個航空公司,莫非這個號就是航空公司的編號?
恭喜你,就是那麼簡單,這個號就對應了服務器端的提供的某一個服務,Android 中每一個Service都有一個號碼(根據建立時間遞增,0號Service 是ServiceManager,讓我用下面的圖來描述整個過程吧,
1. 在已知服務名的狀況下,App 經過getService() 從ServiceManager 獲取該服務的信息,該信息封裝在Parcel裏。
2. 應用程序收到返回的這個Parcel對象(經過Kernel), 從中讀取出flat_binder_object 對象,最終從對象中獲得服務對應的服務號,mHandle.
3. 以該號碼做爲參數輸入生成一個IBinder對象(實際是BpBinder)。
4. 應用獲取該對象後,經過asInterface(IBinder*) 生成服務對應的Proxy對象(BpXXX),並將其強轉爲接口對象(IXXX),而後直接調用接口函數。
5. 全部的接口對象調用最終會走到BpBinder->transact()函數,這個函數調用IPCThreadState->transact()並以Service號做爲參數之一。
6. 最終經過系統調用ioctrl() 進入內核空間,Binder驅動根據傳進來的Service 號尋找該Service正處於等待狀態的Binder Thread, 喚醒它並在該線程內執行相應的函數,並返回結果給APP。
強調一下:
1. 從應用程序的角度來看,他只認識IBinder 和 IMediaPlayer 這兩個類,但真正的實如今BpBinder 和 BpMediaPlayer, 這正是設計模式所推崇的「 Programs to interface, not implementations", 能夠說Android 是一個嚴格遵循設計模式思想精心設計的系統,咱們未來會就這個話題進行深刻的探討。
2. 客戶端應該層層的封裝,最終的目的就是獲取和傳遞這個mHandle 值,從圖中,咱們看到,這個mHandle至來自與IServiceManager, 他是一個管理其餘服務的服務,經過服務的名字咱們能夠拿到這個服務對應的Handle號,相似網絡域名服務系統。可是咱們說了,IServiceManager也是服務啊,要訪問他咱們也須要一個Handle號啊,對了,就如同你必須爲你的機器設置DNS 服務器地址,你才能得到DNS 服務。在Android系統裏, 默認的將ServiceManger的Handler號設爲0,0就是DNS服務器的地址,這樣,咱們經過調用 getStrongProxyForHandle(0) 就能夠拿到ServiceManager 的IBinder 對象,固然,系統提供一個 getService(char *)函數來幫助完成這個過程。
3. Android Binder 的設計目標就是讓訪問遠端服務就像調用本地函數同樣簡單,可是遠端的對象不在本地控制以內,咱們必須保證調用過程當中遠端的對象不能被析構,不然本地應用程序將頗有可能崩潰。同時,萬一遠端服務異常退出,如Crash, 本地對象必須知曉從而避免後續的錯誤。Android 經過 智能指針 和 DeathNotification 來支持這兩個要求,咱們會有專門的章節介紹智能指針,這裏咱們會在後面簡單介紹 DeathNotifycation的實現原理。
Binder的上層設計邏輯簡單介紹完畢。咱們接下來看看Binder的底層設計。
咱們知道,Linux的進程空間相互獨立,兩個進程只能經過Kernel space 進行互訪,全部的IPC 機制,最底層的實現都是在Kernel space. Binder 也是如此,經過系統調用切入內核態,內核尋找到提供服務的進程,喚醒他並進入用戶空間,而後在某個線程裏調用onTransact(), 完成特定操做,並將結果返回到應用程序。那Binder Driver是如何搭起鏈接服務端和客戶端的這座橋樑呢?
先看看binder driver 內部的數據結構吧:
下面一一進行解釋:
1. Binder node:
咱們前面說過Service 實際上是一個存在於某個進程裏的對象,所以,進程PID 和 對象地址能夠惟一的標識一個Service 對象,除此以外,由於這個對象可能被不少應用所使用,必須有引用計數來管理他的生命週期。這些工做都必須在內核裏完成,Binder node 就是這樣一個結構體來管理每一個Service 對象。
struct binder_node { int debug_id; //kernel內部標識node的id struct binder_work work; union { struct rb_node rb_node; struct hlist_node dead_node; }; struct binder_proc *proc; //Service所在進程的結構體 struct hlist_head refs; //雙向鏈表頭,鏈表裏存放一系列指針,指向引用該Service的binder_ref對象, int internal_strong_refs; //內部強引用計數 int local_weak_refs; //弱引用計數 int local_strong_refs; //強引用計數 binder_ptr __user ptr; //Service對象地址 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 描述了每一個對服務對象的引用,對應與Client端。如上圖所示,每一個Ref經過node指向binder_node. 一個進程全部的binder_ref經過兩個紅黑樹(RbTree)進行管理,經過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; //應用進程 struct binder_node *node; uint32_t desc; int strong; int weak; struct binder_ref_death *death; //若是不爲空,則client想獲知binder的死亡 };
3. binder_proc
一個進程既包含的Service對象,也可能包含對其餘Service對象的引用. 若是做爲Service對象進程,它可能會存在多個Binder_Thread。這些信息都在binder_proc結構體進行管理。
struct binder_proc { struct hlist_node proc_node; //全局鏈表 binder_procs 的node之一 struct rb_root threads; //binder_thread紅黑樹,存放指針,指向進程全部的binder_thread, 用於Server端 struct rb_root nodes; //binder_node紅黑樹,存放指針,指向進程全部的binder 對象 struct rb_root refs_by_desc; //binder_ref 紅黑樹,根據desc(service No) 查找對應的引用 struct rb_root refs_by_node; //binder_ref 紅黑樹,根據binder_node 指針查找對應的引用 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鏈表,存放指針最終指向某個binder_transaction對象 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; };
爲了實現快速的查找,binder_proc內部維護了若干個數據結構,如圖中黃色高亮所示,
4. binder_transaction
每一個transact() 調用在內核裏都會生產一個binder_transaction 對象,這個對象會最終送到Service進程或線程的todo隊列裏,而後喚醒他們來最終完成onTransact()調用。
struct binder_transaction { int debug_id; //一個全局惟一的ID struct binder_work work; // 用於存放在todo鏈表裏 struct binder_thread *from; //transaction 發起的線程。若是BC_TRANSACTION, 則爲客戶端線程,若是是BC_REPLY, 則爲服務端線程。 struct binder_transaction *from_parent; //上一個binder_transaction. 用於client端 struct binder_proc *to_proc; //目標進程 struct binder_thread *to_thread; //目標線程 struct binder_transaction *to_parent; //上一個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 紅黑樹存放着指向binder_thread對象的指針。這裏的binder_thread 不只僅包括service的binder thread, 也包括訪問其餘service的調用thread. 也就是說全部與binder相關的線程都會在binder_proc的threads紅黑樹裏留下記錄。binder_thread裏最重要的兩個成員變量是 transaction_stack 和 wait.
struct binder_thread { struct binder_proc *proc; struct rb_node rb_node; //紅黑樹節點 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; //等待隊列,用於阻塞等待 struct binder_stats stats; };
在binder_proc裏面咱們也能看到一個wait 隊列,是否是意味着線程既能夠在proc->wait上等待,也能夠在thread->wait上等待?binder driver 對此有明確的用法,全部的binder threads (server 端)都等待在proc->wait上。由於對於服務端來講,用哪一個thread來響應遠程調用請求都是同樣的。然而全部的ref thread(client端)的返回等待都發生在調用thread的wait 隊列,由於,當某個binder thread 完成服務請求後,他必須喚醒特定的等待返回的線程。可是有一個例外,在雙向調用的狀況下,某個Server端的thread將會掛在thread->wait上等待,而不是proc->wait. 舉個例子,假設兩個進程P1 和 P2,各自運行了一個Service, S1,S2, P1 在 thread T1 裏調用S2提供的服務,而後在T1->wait裏等待返回。S2的服務在P2的binder thread(T2)裏執行,執行過程當中,S2又調到S1裏的某個接口,按理S1 將在P1的binder thread T3裏執行, 若是P1接下來又調到了P2,那又會產生新的進程 T4, 若是這個反覆調用棧很深,須要耗費大量的線程,顯然這是很是不高效的設計。因此,binder driver 裏作了特殊的處理。當T2 調用 S1的接口函數時,binder driver 會遍歷T2的transaction_stack, 若是發現這是一個雙向調用(binder_transaction->from->proc 等於P1), 便會喚醒正在等待reply的T1,T1 完成這個請求後,繼續等待S2的回覆。這樣,只須要最多兩個Thread就能夠完成多層的雙向調用。
binder_thread裏的transaction_stack 是用鏈表實現的堆棧, 調用線程和服務線程的transaction有着不一樣的堆棧。下圖是上面這個例子的堆棧情形:
6. binder_ref_death
binder_ref 記錄了從client進程到server進程某個service的引用,binder_ref_death 是binder_ref的一個成員變量,它的不爲空說明了client進程想獲得這個service的死亡通知(嚴格意義上講,是service所在進程的死亡通知,由於一個進程一個/dev/binder的fd, 只有進程死亡了,driver纔會知曉,經過 file_operations->release 接口)。
struct binder_ref_death { struct binder_work work; binder_ptr __user cookie; };
咱們能夠下面一張時序圖來了解binder death notifycation 的全過程。
7. binder_work
從應用程序角度來看,全部的binder調用都是同步的。但在binder driver 內部,兩個進程間的交互都是異步的,一個進程產生的請求會變成一個binder_work, 並送入目標進程或線程的todo 隊列裏,而後喚醒目標進程和線程來完成這個請求,並阻塞等待結果。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; };
很簡單,其實只定義了一個鏈表的節點和work的類型。
8. binder_buffer
進程間通訊除了命令,還有參數和返回值的交換,要將數據從一個進程的地址空間,傳到另一個進程的地址空間,一般須要兩次拷貝,進程A -> 內核 -> 進程B。binder_buffer 就是內核裏存放交換數據的空間(這些數據是以Parcel的形式存在)。爲了提升效率,Android 的 binder 只須要一次拷貝,由於binder 進程經過mmap將內核空間地址映射到用戶空間,從而能夠直接訪問binder_buffer的內容而無需一次額外拷貝。binder_buffer由內核在每次發起的binder調用建立,並賦給binder_transaction->buffer. binder driver 根據binder_transaction 生產 transaction_data(包含buffer的指針而非內容), 並將其複製到用戶空間。
9. flat_binder_obj
前面咱們說過,<proc, handle> 能夠標識一個BpBinder 對象,而<proc, ptr> 能夠標識一個BBinder對象。Binder Driver 會收到來自與BpBinder 和 BBinder的系統調用,它是如何判別它們的身份呢?答案就在flat_binder_obj裏,先看看它的定義,
struct flat_binder_object { unsigned long type; //見下面定義 unsigned long flags; union { void *binder; //BBinder,經過它driver能夠找到對應的node signed long handle; //BpBinder,根據它driver能夠找到對應的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 根據它能夠找到BpBinder 和 BBinder 在內核中相對應的對象 (ref 或 node). flat_binder_obj 封裝在parcel裏,詳見Parcel.cpp.
至此,binder driver裏面重要的數據結構都介紹完了,你們對binder driver的工做原理也有了大體的瞭解,這裏再稍做總結:
1. 當一個service向binder driver 註冊時(經過flat_binder_object), driver 會建立一個binder_node, 並掛載到該service所在進程的nodes紅黑樹。
2. 這個service的binder線程在proc->wait 隊列上進入睡眠等待。等待一個binder_work的到來。
3. 客戶端的BpBinder 建立的時候,它在driver內部也產生了一個binder_ref對象,並指向某個binder_node, 在driver內部,將client和server關聯起來。若是它須要或者Service的死亡狀態,則會生成相應的binfer_ref_death.
4. 客戶端經過transact() (對應內核命令BC_TRANSACTION)請求遠端服務,driver經過ref->node的映射,找到service所在進程,生產一個binder_buffer, binder_transaction 和 binder_work 並插入proc->todo隊列,接着喚醒某個睡在proc->wait隊列上的Binder_thread. 與此同時,該客戶端線程在其線程的wait隊列上進入睡眠,等待返回值。
5. 這個binder thread 從proc->todo 隊列中讀出一個binder_transaction, 封裝成transaction_data (命令爲 BR_TRANSACTION) 並送到用戶空間。Binder用戶線程喚醒並最終執行對應的on_transact() 函數。
6. Binder用戶線程經過transact() 向內核發送 BC_REPLY命令,driver收到後從其thread->transaction_stack中找到對應的binder_transaction, 從而知道是哪一個客戶端線程正在等待這個返回。
7. Driver 生產新的binder_transaction (命令 BR_REPLY), binder_buffer, binder_work, 將其插入應用線程的todo對立,並將該線程喚醒。
8. 客戶端的用戶線程收到回覆數據,該Transaction完成。
9. 當service所在進程發生異常退出,driver 的 release函數被調到,在某位內核work_queue 線程裏完成該service在內核態的清理工做(thread,buffer,node,work...), 並找到全部引用它的binder_ref, 若是某個binder_ref 有不爲空的binder_ref_death, 生成新的binder_work, 送人其線程的todo 對立,喚醒它來執行剩餘工做,用戶端的DeathRecipient 會最終被調用來完成client端的清理工做。
下面這張時序圖描述了上述一個transaction完成的過程。不一樣的顏色表明不一樣的線程。注意的是,雖然Kernel和User space 線程的顏色是不同的,但全部的系統調用都發生在用戶進程的上下文裏(所謂上下文,就是Kernel能經過某種方式找到關聯的進程(經過Kernel的current 宏),並完成進程相關的操做,好比說喚醒某個睡眠的線程,或跟用戶空間交換數據,copy_from, copy_to, 與之相對應的是中斷上下文,其徹底異步觸發,所以沒法作任何與進程相關的操做,好比說睡眠,鎖等)。
Binder 的學習已經接近尾聲了,咱們已經研究了Binder Driver, C/C++的實現,就差最後一個部分了,Binder在Java端的實現了。Java端的實現與Native端相似,咱們用下面的表格和類圖歸納他們的關係
Native | Java | Note |
IBinder | IBinder | |
IInterface | IInterface | |
IXXX | IXXX | aidl文件定義 |
BBinder | Binder | 經過JavaBBinder類做爲橋樑 |
BpBinder | BinderProxy | 經過JNI訪問Native的實現 |
BnInterface | N/A | |
BpInterface | N/A | |
BnXXX | Stub | aidl工具自動生成 |
BpXXX | Proxy | aidl工具自動生成 |
可見,Java較Native端實現簡單不少,經過Aidl工具來實現相似功能。因此,要實現一個Java端的service,只須要作如下幾件事情:
1. 寫一個.aidl文件,裏面用AIDL語言定義一個接口類IXXX。
2.在Android.mk里加入該文件,這樣編譯系統會自動生成一個IXXX.java, 放在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core 下面。
3. 在服務端,寫一個類,擴展IXXX.Stub,具體實現IXXX的接口函數。