Android系统的Binder机制之二——服务代理对象(1)
上文《Android系统的Binder机制之一——Service Manager》我们学习了Service Manager在Android Binder中的作用——服务(Service)注册,服务(Service)查询的功能。本文我们一起学习服务(Service)在客户端中的代理机制。重点介绍其核心对象BpBinder。
1、服务代理的原理
如下是客户端请求service服务的场景:
1、首先客户端向Service manager查找相应的Service。上文《Android系统的Binder机制之一——Service Manager》有比较详细的介绍。注意客户端和Service可能在两个不同的进程中。
2、Android系统将会为客户端进程中创建一个Service代理。下文将详细介绍该创建过程。
3、客 户端视角只有Service代理,他所有对Service的请求都发往Service代理,然后有Service代理把用户请求转发给Service本 身。Service处理完成之后,把结果返回给Service代理,Service代理负责把处理结果返回给客户端。注意客户端对Service代理的调 用都是同步调用(调用挂住,直到调用返回为止),这样客户端视角来看调用远端Service的服务和调用本地的函数没有任何区别。这也是Binder机制 的一个特点。
2、Android进程环境——ProcessState类型和对象
在Android系统中任进程何,要想使用Binder机制,必须要创建一个ProcessState对象和IPCThreadState对象。当然如果 Android进程不使用Binder机制,那么这两个对象是不用创建的。这种情况很少见,因为Binder机制是整个Android框架的基础,可以说 影响到Android方方面面。所以说了解这两个对象的作用非常重要。
台湾的高焕堂先生一片文章《认识ProcessState类型和对象》,可以在我的博文《(转)高焕堂——Android框架底层结构知多少?》中找到。可以先通过这篇文章对ProcessState进行一个大概了解。
ProcessState是一个singleton类型,一个进程只能创建一个他的对象。他的作用是维护当前进程中所有Service代理(BpBinder对象)。一个客户端进程可能需要多个Service的服务,这样可能会创建多个Service代理(BpBinder对象),客户端进程中的ProcessState对象将会负责维护这些Service代理。
我们研究一下创建一个Service代理的代码:
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: }
当前进程首先调用lookupHandleLocked函数去查看当前进程维护的Service代理对象的列表,该待创建Service代理对象是否已经 在当前进程中创建,如果已经创建过了,则直接返回其引用就可以了。否则将会在Service代理对象的列表增加相应的位置(注意系统为了减少分配开销,可 能会多分配一些空间,策略是“以空间换时间”),保存将要创建的代理对象。具体代码请参考lookupHandleLocked的源码。
后面代码就好理解了,如果Service代理对象已经创建过了,直接增加引用计数就行了。若没有创建过,则需要创建一个新的Service代理对象。
3、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: }
1: friend class 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: ...........
1、维护当前进程中所有对/dev/binder的读写。换句话说当前进程通过binder机制进行跨进程调用都是通过IPCThreadState对象来完成的。
2、IPCThreadState也可以理解成/dev/binder设备的封装,用户可以不直接通过ioctl来操作binder设备,都通过IPCThreadState对象来代理即可。
4、Service代理对象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: }
客户进程对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: }
5、Android系统对Binder机制的抽象——IBinder
上面我们讲解了Binder机制比较底层的机制,这些机制直接用还是比较麻烦的,比如使用binder设备的ioctl,需要记住很多ioctl的代码。
Android为了是Binder机制容易使用,对Binder机制进行了抽象,定义了IBinder接口,该接口在C/C++和Java层都有定义。IBinder定义了一套使用Binder机制使用和实现客户程序和服务器的通讯协议。可以理解如下定义:
1、向Android注册的Service也必须是IBinder(继承扩展IBinder接口)对象。后续文章中我们讨论Service的时候我们会介绍到这方面的内容。
2、客户端得到Service代理对象也必须定义成IBinder(继承扩展IBinder接口)对象。这也是为什么BpBinder就是继承自IBinder。3、客户端发送请求给客户端,调用接口的Service代理对象IBinder接口的transact方法。
4、Android系统Binder机制将负责把用户的请求,调用Service对象IBinder接口的onTransact方法。具体实现我们将在以后介绍Service的时候讨论。
6、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的时候将会详细介绍。
7、总结
本文中我们介绍了C++层面的Service代理,后续文章我们将介绍Java层面的Service代理。