Android系統的Binder機制之二——服務代理對象(1)

  上文《Android系統的Binder機制之一——Service Manager》咱們學習了Service Manager在Android Binder中的做用——服務(Service)註冊,服務(Service)查詢的功能。本文咱們一塊兒學習服務(Service)在客戶端中的代理機制。重點介紹其核心對象BpBinder。 
android

一、服務代理的原理

    以下是客戶端請求service服務的場景:服務器

一、首先客戶端向Service manager查找相應的Service。上文《Android系統的Binder機制之一——Service Manager》有比較詳細的介紹。注意客戶端和Service可能在兩個不一樣的進程中。 
二、Android系統將會爲客戶端進程中建立一個Service代理。下文將詳細介紹該建立過程。 
三、
客戶端視角只有Service代理,他全部對Service的請求都發往Service代理,而後有Service代理把用戶請求轉發給Service自己。Service處理完成以後,把結果返回給Service代理,Service代理負責把處理結果返回給客戶端。注意客戶端對Service代理的調用都是同步調用(調用掛住,直到調用返回爲止),這樣客戶端視角來看調用遠端Service的服務和調用本地的函數沒有任何區別。這也是Binder機制的一個特色框架

二、Android進程環境——ProcessState類型和對象

    在Android系統中任進程何,要想使用Binder機制,必需要建立一個ProcessState對象和IPCThreadState對象。固然若是Android進程不使用Binder機制,那麼這兩個對象是不用建立的。這種狀況不多見,由於Binder機制是整個Android框架的基礎,能夠說影響到Android方方面面。因此說了解這兩個對象的做用很是重要。函數

    臺灣的高煥堂先生一片文章《認識ProcessState類型和對象》,能夠在個人博文《(轉)高煥堂——Android框架底層結構知多少?》中找到。能夠先經過這篇文章對ProcessState進行一個大概瞭解。學習

    ProcessState是一個singleton類型,一個進程只能建立一個他的對象。他的做用是維護當前進程中全部Service代理(BpBinder對象)。一個客戶端進程可能須要多個Service的服務,這樣可能會建立多個Service代理(BpBinder對象),客戶端進程中的ProcessState對象將會負責維護這些Service代理。ui

咱們研究一下建立一個Service代理的代碼:this

 1: sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)

 2: {

 3:     sp<IBinder> result;

 4: 

 5:     AutoMutex _l(mLock);

 6: 

 7:     handle_entry* e = lookupHandleLocked(handle);

 8: 

 9:     if (e != NULL) {

 10:         // We need to create a new BpBinder if there isn't currently one, OR we

 11:         // are unable to acquire a weak reference on this current one. See comment

 12:         // in getWeakProxyForHandle() for more info about this.

 13:         IBinder* b = e->binder;

 14:         if (b == NULL || !e->refs->attemptIncWeak(this)) {

 15:             b = new BpBinder(handle);

 16:             e->binder = b;

 17:             if (b) e->refs = b->getWeakRefs();

 18:             result = b;

 19:         } else {

 20:             // This little bit of nastyness is to allow us to add a primary

 21:             // reference to the remote proxy when this team doesn't have one

 22:             // but another team is sending the handle to us.

 23:             result.force_set(b);

 24:             e->refs->decWeak(this);

 25:         }

 26:     }

 27: 

 28:     return result;

 29: }

    getWeakProxyForHandle函數的做用是根據一個binder句柄(上文《 Android系統的Binder機制之一——Service Manager 》提到Binder驅動爲每一個Service維護一個Binder句柄,客戶端能夠經過句柄來和Service通信)建立對應的Service代理對象。

    當前進程首先調用lookupHandleLocked函數去查看當前進程維護的Service代理對象的列表,該待建立Service代理對象是否已經在當前進程中建立,若是已經建立過了,則直接返回其引用就能夠了。不然將會在Service代理對象的列表增長相應的位置(注意系統爲了減小分配開銷,可能會多分配一些空間,策略是「以空間換時間」),保存將要建立的代理對象。具體代碼請參考lookupHandleLocked的源碼。spa

    後面代碼就好理解了,若是Service代理對象已經建立過了,直接增長引用計數就好了。若沒有建立過,則須要建立一個新的Service代理對象。.net

三、Android進程環境——IPCThreadState類型和對象

    Android進程中能夠建立一個ProcessState對象,該對象建立過程當中會打開/dev/binder設備,並保存其句柄。並初始化該設備。代碼以下:線程

 1: ProcessState::ProcessState()

 2:     : mDriverFD(open_driver())

 3:     , mVMStart(MAP_FAILED)

 4:     , mManagesContexts(false)

 5:     , mBinderContextCheckFunc(NULL)

 6:     , mBinderContextUserData(NULL)

 7:     , mThreadPoolStarted(false)

 8:     , mThreadPoolSeq(1)

 9: {

 10:     if (mDriverFD >= 0) {

 11:         // XXX Ideally, there should be a specific define for whether we

 12:         // have mmap (or whether we could possibly have the kernel module

 13:         // availabla).

 14: #if !defined(HAVE_WIN32_IPC)

 15:         // mmap the binder, providing a chunk of virtual address space to receive transactions.

 16:         mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);

 17:         if (mVMStart == MAP_FAILED) {

 18:             // *sigh*

 19:             LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");

 20:             close(mDriverFD);

 21:             mDriverFD = -1;

 22:         }

 23: #else

 24:         mDriverFD = -1;

 25: #endif

 26:     }

 27:     if (mDriverFD < 0) {

 28:         // Need to run without the driver, starting our own thread pool.

 29:     }

 30: }

    mDriverFD保存了/dev/binder設備的句柄,若是仔細查看ProcessState的源碼會發現這個句柄不會被ProcessState對象使用。那麼保存這個句柄作什麼用呢?被誰使用呢?很是奇怪。通過查看ProcessState的頭文件,發現以下代碼:
 1: friend class IPCThreadState;

    發現IPCThreadState是ProcessState的友元類,那麼就能夠懷疑這個句柄是被IPCThreadState的對象使用的,而後查看代碼發現確實如此。

    IPCThreadState也是一個singleton的類型,一個進程中也只能有一個這樣的對象。咱們查看一下它的talkWithDriver函數:

 1: ...........

 2: if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)

 3:     err = NO_ERROR;

 4: else

 5:     err = -errno;

 6: ...........

    IPCThreadState經過ioctl系統調用對ProcessState打開的句柄進行讀寫。這樣咱們也能夠看出IPCThreadState對象的做用:
一、維護當前進程中全部對/dev/binder的讀寫。換句話說當前進程經過binder機制進行跨進程調用都是經過IPCThreadState對象來完成的。

二、
IPCThreadState也能夠理解成/dev/binder設備的封裝,用戶能夠不直接經過ioctl來操做binder設備,都經過IPCThreadState對象來代理便可。
     咱們這裏能夠再深刻地聊一下,不論是客戶端進程和Service進程都是須要用IPCThreadState來和binder設備通信的。若是是客戶端進程則經過服務代理BpBinder對象,調用transact函數,該函數做用就是把客戶端的請求寫入binder設備另外一端的Service進程,具體請參閱IPCThreadState類的transact方法。做爲Service進程,當他完成初始化工做以後,他須要他們須要進入循環狀態等待客戶端的請求,Service進程調用它的IPCThreadState對象的joinThreadPool方法,開始輪詢binder設備,等待客戶端請求的到來,後面咱們討論Service時候會進一步討論joinThreadPool方法。有興趣的朋友能夠先經過查看代碼來了解joinThreadPool方法。

四、Service代理對象BpBinder

    上文關於ProcessState的介紹提到了,客戶端進程建立的Service代理對象其實就是BpBinder對象。
    咱們首先了解怎樣建立BpBinder對象。
 1: BpBinder::BpBinder(int32_t handle)

 2:     : mHandle(handle)

 3:     , mAlive(1)

 4:     , mObitsSent(0)

 5:     , mObituaries(NULL)

 6: {

 7:     LOGV("Creating BpBinder %p handle %d\n", this, mHandle);

 8: 

 9:     extendObjectLifetime(OBJECT_LIFETIME_WEAK);

 10:     IPCThreadState::self()->incWeakHandle(handle);

 11: }

    咱們能夠看出首先是經過IPCThreadState讀寫binder設備增長中相應binder句柄上的Service的引用計數。而後本地保存代理Service的binder句柄mHandle。

    客戶進程對Service的請求都經過調用BpBinder的transact方法來完成:

 1: status_t BpBinder::transact(

 2:     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

 3: {

 4:     // Once a binder has died, it will never come back to life.

 5:     if (mAlive) {

 6:         status_t status = IPCThreadState::self()->transact(

 7:             mHandle, code, data, reply, flags);

 8:         if (status == DEAD_OBJECT) mAlive = 0;

 9:         return status;

 10:     }

 11: 

 12:     return DEAD_OBJECT;

 13: }

在transact方法中,仍是調用客戶進程的IPCThreadState對象來完成對相應Service請求。注意transact方法是同步方法,將會掛住客戶進程的當前線程,直到service把請求處理完成,並返回結果。這時客戶進程當前線程的transact方法返回。

五、Android系統對Binder機制的抽象——IBinder

    上面咱們講解了Binder機制比較底層的機制,這些機制直接用仍是比較麻煩的,好比使用binder設備的ioctl,須要記住不少ioctl的代碼。

    Android爲了是Binder機制容易使用,對Binder機制進行了抽象,定義了IBinder接口,該接口在C/C++和Java層都有定義。IBinder定義了一套使用Binder機制使用和實現客戶程序和服務器的通信協議。能夠理解以下定義:

一、向Android註冊的Service也必須是IBinder(繼承擴展IBinder接口)對象。後續文章中咱們討論Service的時候咱們會介紹到這方面的內容。

二、客戶端獲得Service代理對象也必須定義成IBinder(繼承擴展IBinder接口)對象。這也是爲何BpBinder就是繼承自IBinder。

三、客戶端發送請求給客戶端,調用接口的Service代理對象IBinder接口的transact方法。

四、Android系統Binder機制將負責把用戶的請求,調用Service對象IBinder接口的onTransact方法。具體實現咱們將在之後介紹Service的時候討論。

六、Service Manager代理對象

    咱們知道Service Manager是Android Binder機制的大管家。全部須要經過Binder通信的進程都須要先得到Service Manager的代理對象才能進行Binder通信。Service Manager即在C/C++層面提供服務代理,又在Java層面提供服務代理,本文先介紹一下C/C++層面的服務代理,Java層面的服務代理將在後續文章中介紹。

    進程在C/C++層面上面,Android在Android命名空間中定義了一個全局的函數defaultServiceManager(定義在framework/base/libs/binder),經過這個函數可使進程在C/C++層面得到Service Manager的代理。咱們先看一下該函數的定義:

 1: sp<IServiceManager> defaultServiceManager()

 2: {

 3:     if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

 4:

 5:     {

 6:         AutoMutex _l(gDefaultServiceManagerLock);

 7:         if (gDefaultServiceManager == NULL) {

 8:             gDefaultServiceManager = interface_cast<IServiceManager>(

 9:                 ProcessState::self()->getContextObject(NULL));

 10:         }

 11:     }

 12:

 13:     return gDefaultServiceManager;

 14: }

    咱們能夠看到defaultServiceManager是調用ProcessState對象的getContextObject方法得到Service Manager的getContextObject方法得到Service Manager代理對象。咱們再看一下getContextObject函數的定義:

 1: sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)

 2: {

 3:     if (supportsProcesses()) {

 4:         return getStrongProxyForHandle(0);

 5:     } else {

 6:         return getContextObject(String16("default"), caller);

 7:     }

 8: }

    咱們能夠看出實際上是調用咱們上面描述過的getStrongProxyForHandle方法,並以句柄0爲參數來得到Service Manager的代理對象。

    ProcessState::self()->getContextObject(NULL)返回一個IBinder對象,怎樣把它轉化成一個IServiceManager的對象呢?這就是模板函數interface_cast<IServiceManager>的做用了。調用的是IServiceManager.asInterface方法。IServiceManager的asInterface方法經過DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE宏來定義,詳細狀況請查看IServiceManager類的定義。IMPLEMENT_META_INTERFACE宏關於asInterface的定義以下:

 1: android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \

 2:         const android::sp<android::IBinder>& obj)                   \

 3: {                                                                   \

 4:     android::sp<I##INTERFACE> intr;                                 \

 5:     if (obj != NULL) {                                              \

 6:         intr = static_cast<I##INTERFACE*>(                          \

 7:             obj->queryLocalInterface(                               \

 8:                     I##INTERFACE::descriptor).get());               \

 9:         if (intr == NULL) {                                         \

 10:             intr = new Bp##INTERFACE(obj);                          \

 11:         }                                                           \

 12:     }                                                               \

 13:     return intr;                                                    \

 14: }                                                                   \

    最終asInterface將會用一個IBinder對象建立一個BpServiceManager對象,而且BpServiceManager繼承自IServiceManager,這樣咱們就把IBinder對象轉換成了IServiceManager對象。若是你仔細查看BpServiceManager的定義,你會發現查詢Service,增長Service等方法其實都是調用底層的IBinder對象來完成的。

    當咱們在C/C++層面編寫程序使用Binder機制的時候將會調用defaultServiceManager函數來得到Service Manager,好比:不少Android系統Service都是在C/C++層面實現的,他們就須要向Service Manager註冊其服務,那麼這些服務將調用defaultServiceManager得到Service Manager代理對象。咱們在後續介紹Android系統Service的時候將會詳細介紹。

七、總結

    本文中咱們介紹了C++層面的Service代理,後續文章咱們將介紹Java層面的Service代理。

相關文章
相關標籤/搜索