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代理。