Android Binder进程间通信---ServiceManager代理对象的获取过程
本文参考《Android系统源代码情景分析》,作者罗升阳。
一、测试代码:
~/Android/external/binder/server
----FregServer.cpp
~/Android/external/binder/common
----IFregService.cpp
----IFregService.h
~/Android/external/binder/client
----FregClient.cpp
Binder库(libbinder)代码:
~/Android/frameworks/base/libs/binder
----BpBinder.cpp
----Parcel.cpp
----ProcessState.cpp
----Binder.cpp
----IInterface.cpp
----IPCThreadState.cpp
----IServiceManager.cpp
----Static.cpp
~/Android/frameworks/base/include/binder
----Binder.h
----BpBinder.h
----IInterface.h
----IPCThreadState.h
----IServiceManager.h
----IBinder.h
----Parcel.h
----ProcessState.h
驱动层代码:
~/Android//kernel/goldfish/drivers/staging/android
----binder.c
----binder.h
二、源码分析
1、程序首先开始从Service进程FregServer.cpp的main函数开始执行
~/Android/external/binder/server
----FregServer.cpp
class FregService : public BnFregService { ........... public: static void instantiate() { defaultServiceManager()->addService(String16(FREG_SERVICE), new FregService()); } ........... }; int main(int argc, char** argv) { FregService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return 0; }main函数首先调用静态方法instantiate,在instantiate中调用了defaultServiceManager(),defaultServiceManager()函数实现如下:
~/Android/frameworks/base/libs/binder
----IServiceManager.cpp
sp<IServiceManager> defaultServiceManager() { if (gDefaultServiceManager != NULL) return gDefaultServiceManager;//如果已经创建了代理对象,那么就直接返回 { AutoMutex _l(gDefaultServiceManagerLock);//使用锁,来实现单例模式 if (gDefaultServiceManager == NULL) { gDefaultServiceManager = interface_cast<IServiceManager>(//分三步获取Service Manager代理对象 ProcessState::self()->getContextObject(NULL)); } } return gDefaultServiceManager; }其中gDefaultServiceManagerLock,gDefaultServiceManager都定义在Static.cpp中。
~/Android/frameworks/base/libs/binder
----Static.cpp
Mutex gDefaultServiceManagerLock; //锁 sp<IServiceManager> gDefaultServiceManager; //IServiceManager的强指针全局变量gDefaultServiceManager是一个类型为IServiceManager的强指针,它指向进程内的一个BpServiceManager对象,即Service Manager代理对象;而全局变量gDefaultServiceManagerLock是用来保证一个进程至多只有一个Service Manager代理对象。结合锁机制来保证对象在进程中的唯一性,这是单例设计模式的经典实现。
如果已经创建了代理对象,那么就直接返回。如果没有创建,那么分三步创建:
(1)、调用ProcessState类的静态成员函数self获取进程内的一个ProcessState对象。
(2)、调用前面获得的ProcessState对象的成员函数getContextObject创建一个Binder代理对象
(3)、调用模板函数interface_cast<IServiceManager>将前面获得的Binder代理对象封装成一个Service Manager代理对象。
2、调用ProcessState类的静态成员函数self获取进程内的一个ProcessState对象
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
sp<ProcessState> ProcessState::self() { if (gProcess != NULL) return gProcess;//如果已经创建了,就直接返回 AutoMutex _l(gProcessMutex); if (gProcess == NULL) gProcess = new ProcessState;//创建ProcessState对象 return gProcess; }其中gProcess,gProcessMutex都位于Static.cpp中
Mutex gProcessMutex; sp<ProcessState> gProcess;全局变量gProcess是一个类型为ProcessState的强指针,它指向进程内的一个ProcessState对象;而全局变量gProcessMutex是一个互斥锁,是用来保证一个进程至多只有一个ProcessState对象的,同样是一个单例模式。
首次进入,故创建ProcessState对象。
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
ProcessState::ProcessState() : mDriverFD(open_driver()) , mVMStart(MAP_FAILED) ..... { if (mDriverFD >= 0) { ........... // mmap the binder, providing a chunk of virtual address space to receive transactions. mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); ........... }在初始化构造函数中调用了open_driver方法。
~/Android/frameworks/base/libs/binder
static int open_driver() { if (gSingleProcess) { return -1; } int fd = open("/dev/binder", O_RDWR);//又一个进程打开了设备文件,binder_procs又多了一个进程的结构体 if (fd >= 0) { fcntl(fd, F_SETFD, FD_CLOEXEC); int vers; #if defined(HAVE_ANDROID_OS) status_t result = ioctl(fd, BINDER_VERSION, &vers);//调用ioctl传入BINDER_VERSION参数来获取vers #else status_t result = -1; errno = EPERM; #endif if (result == -1) { LOGE("Binder ioctl to obtain version failed: %s", strerror(errno)); close(fd); fd = -1; } if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) { LOGE("Binder driver protocol does not match user space protocol!"); close(fd); fd = -1; } #if defined(HAVE_ANDROID_OS) size_t maxThreads = 15; result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//调用ioctl传入BINDER_SET_MAX_THREADS参数来设备该进程所支持的最大线程数 if (result == -1) { LOGE("Binder ioctl to set max threads failed: %s", strerror(errno)); } #endif } else { LOGW("Opening ‘/dev/binder‘ failed: %s\n", strerror(errno)); } return fd; }open_driver首先调用了open打开设备文件,在http://blog.csdn.net/jltxgcy/article/details/25797011这盘文章中已经讲解了驱动层的binder_open所做的事。然后的调用ioctl传入BINDER_VERSION参数来获取vers。最后调用ioctl传入BINDER_SET_MAX_THREADS参数来设备该进程所支持的最大线程数。
在初始化列表中调用mmap把设备文件/dev/binder映射到进程的地址空间,其实将/dev/binder映射到进程的地址空间实际上是请求Binder驱动程序为进程分配内核缓冲区。
3、调用前面获得的ProcessState对象的成员函数getContextObject创建一个Binder代理对象
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) { if (supportsProcesses()) {//为true return getStrongProxyForHandle(0); } else { return getContextObject(String16("default"), caller); } }
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
bool ProcessState::supportsProcesses() const { return mDriverFD >= 0; }由于在open_driver时,mDriverFD已经大于0,所以程序开始执行getStrongProxyForHandle(0)。
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle);//检查成员变量mHandleToObject是否已经存在一个与句柄值handle对应的handle_entry结构体 if (e != NULL) { // We need to create a new BpBinder if there isn‘t currently one, OR we // are unable to acquire a weak reference on this current one. See comment // in getWeakProxyForHandle() for more info about this. IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) {//如果进程尚未为句柄值handle创建过Binder代理对象,或者创建了Binder代理对象但已经销毁了 b = new BpBinder(handle); //Binder代理对象,handle为0 e->binder = b;//保存再e的成员变量binder中 if (b) e->refs = b->getWeakRefs();//将弱引用计数对象保存在e的成员变量refs中 result = b;//返回结果 } else {//如果进程已经创建了Binder代理对象,并且没有销毁,那么直接返回 // This little bit of nastyness is to allow us to add a primary // reference to the remote proxy when this team doesn‘t have one // but another team is sending the handle to us. result.force_set(b);//设置返回结果result e->refs->decWeak(this);//减少弱引用计数,因为attemptIncWeak增加了弱引用计数 } } return result; }参数handle的值等于0,表示要创建的Binder代理对象的句柄值等于0,即要创建一个Binder代理对象。Binder库为每个进程维护了一个handle_entry类型的Binder代理对象列表,它以句柄值作为关键字来维护进程内部所有的Binder代理对象。这个Binder代理对象列表保存在ProcessState类的成员变量mHandleToObject,它的定义如下:
~/Android/frameworks/base/include/binder
----ProcessState.h
class ProcessState : public virtual RefBase { ....... struct handle_entry { IBinder* binder;//Binder代理对象 RefBase::weakref_type* refs;//一个弱引用计数对象 }; .......... Vector<handle_entry>mHandleToObject;//列表 ......... };
每一个Binder代理对象都使用一个handle_entry结构体来描述。结构体handle_entry的两个成员变量binder和refs分别指向一个Binder代理对象,以及它内部的一个弱引用计数对象。
回到ProcessState类的成员函数getStrongProxyForHandle(0),首先调用成员函数lookupHandleLocked来检查成员变量mHandleToObject是否已经存在一个与句柄值handle对应的handle_entry结构体,它的实现如下:
~/Android/frameworks/base/libs/binder
----ProcessState.cpp
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle) { const size_t N=mHandleToObject.size();//列表的大小 if (N <= (size_t)handle) {如果句柄值大于或者等于列表大小,否则直接返回指向该结构体的指针 handle_entry e;//创建handle_entry结构体 e.binder = NULL;//初始化 e.refs = NULL; status_t err = mHandleToObject.insertAt(e, N, handle+1-N);//插入到对应位置 if (err < NO_ERROR) return NULL; } return &mHandleToObject.editItemAt(handle);//返回指向该结构体的指针 }一个Binder代理对象的句柄值同时也是它在列表mHandleToObject中的索引值。首先检查句柄值handle是否大于或者等于列表mHandleToObject的大小,如果是,那么mHandleToObject列表里面就不存在一个与句柄值handle对应的handle_entry结构体,那么创建一个handle_entry结构体,并插入到对应位置,最后返回指向该结构体的指针。
程序继续执行,如果hanle_entry结构体e的成员变量binder的值为NULL,说明进程尚未为句柄值handle创建过Binder代理对象,因此就会根据句柄值handle创建一个Binder代理对象,并且将它保存在handle_entry结构体e的成员变量binder中。并且把弱引用计数对象保存在e的成员变量refs中。
如果hanle_entry结构体e的成员变量binder的值不为NULL,即它已经指向了一个Binder代理对象,就需要继续检查这个Binder代理对象是否还活着,方法是调用它的弱引用计数对象的成员函数attemptIncWeek来尝试增加它的弱引用数。由于Binder代理对象(即BpBinder对象)的生命周期是受弱引用计数控制的,因此如果不能成功增加它的弱引用计数,那么就说明它已经被销毁了。在这种情况下,也需要重新为句柄值handle创建一个Binder代理对象。
如果handle_entry结构体e成员变量binder的值不等于NULL,并且调用它的成员attmptIncWeek能够成功地增加与它对应的一个Binder代理对象的弱引用计数,那么就说明在进程中已经有一个Binder代理对象与句柄值handle相对应,并且这个Binder代理对象是有效的,因此,可以直接将它返回调用调用者。注意函数在将这个Binder代理对象返回给调用者之前,会减少它的弱引用计数,因为attemptIncWeek增加了弱应用计数。
下面我们分析下如何创建Binder代理对象,即new BpBinder(handle)究竟做了什么?
~/Android/frameworks/base/include/binder
----BpBinder.cpp
BpBinder::BpBinder(int32_t handle) : mHandle(handle)//mHandle等于0 , mAlive(1) , mObitsSent(0) , mObituaries(NULL) { LOGV("Creating BpBinder %p handle %d\n", this, mHandle); extendObjectLifetime(OBJECT_LIFETIME_WEAK); IPCThreadState::self()->incWeakHandle(handle);//调用了IPCThreadState的成员函数self() }又调用了IPCThreadState的成员函数self(),实现如下:
~/Android/frameworks/base/libs/binder
----IPCThreadState.cpp
IPCThreadState* IPCThreadState::self() { if (gHaveTLS) {//第二次为true restart: const pthread_key_t k = gTLS;//利用第一次创建的gTLS IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);//获取IPCThreadState类,有pthread_getspecific(k),就一定有phread_setspecific if (st) return st; return new IPCThreadState;//构造函数中有phread_setspecific } if (gShutdown) return NULL; pthread_mutex_lock(&gTLSMutex); if (!gHaveTLS) {//第一次执行这里,创建了gTLS if (pthread_key_create(&gTLS, threadDestructor) != 0) { pthread_mutex_unlock(&gTLSMutex); return NULL; } gHaveTLS = true;//为第二次做准备 } pthread_mutex_unlock(&gTLSMutex); goto restart;//返回开头 }第一次,gHaveTLS为false,所以进入下面的代码,创建了gTLS,而且gHaveTLS为true。第二次gHaveTLS为true,利用第一次创建的gTLS,获取IPCThreadState类,如果获取不到,就创建该类,在创建该类的过程中,调用了phread_setspecific函数,new IPCThreadState实现如下:
~/Android/frameworks/base/libs/binder
----IPCThreadState.cpp
IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()),//因为单例模式,就是刚才创建的ProcessState对象 mMyThreadId(androidGetTid()), mStrictModePolicy(0), mLastTransactionBinderFlags(0) { pthread_setspecific(gTLS, this);//调用了这个函数,下次就是pthread_getspecific获取到了 clearCaller(); mIn.setDataCapacity(256);//输入容量256 mOut.setDataCapacity(256);//输出容量256 }由于是单例模式,所以mProcess保存的就是刚刚创建的ProcessState对象。下次调用IPCThreadState::self只要在同一个线程中,就返回刚刚创建的IPCThreadState对象,因为每个进程有独一无二的gTLS。
4、调用模板函数interface_cast<IServiceManager>将前面获得的Binder代理对象封装成一个Service Manager代理对象。
~/Android/frameworks/base/include/binder
----IInterface.h
template<typename INTERFACE> inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) { return INTERFACE::asInterface(obj); }由于INTERFACE为IServiceManger,所以展开如下:
template<typename IServiceManager> inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj) { return IServiceManager::asInterface(obj); }调用IServiceManager接口的成员函数asInterface,将一个句柄值为0的Binder代理对象封装为一个Service Manger代理对象。
IServiceManager接口的成员函数asInterface是通过宏IMPLEMENT_META_INTERFACE实现,如下所示:
~/Android/frameworks/base/libs/binder
----IServiceManager.cpp
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");展开后如下:
android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj) { android::sp<IServiceManager> intr; if (obj != NULL) { intr = static_cast<IServiceManager*>( obj->queryLocalInterface(IServiceManager::descriptor).get());//返回NULL if (intr == NULL) { intr = new BpServiceManager(obj); //创建了Service Manager代理对象 } } return intr; }参数obj指向一个Binder代理对象,即一个BpBinder对象,它的成员函数queryLocalInterface的返回值为NULL。因此,最后会创建一个Service Manager代理对象,即一个BpServiceManger对象,并且将它的IServiceManager接口返回给调用者。
uml类图如下:
BpBinder代理对象被保存在BpRefBase类的成员变量mRemote中。
Android Binder进程间通信---ServiceManager代理对象的获取过程,布布扣,bubuko.com