Android Binder进程间通信---ServiceManager代理对象的获取过程

时间:2014-05-18 18:21:12   收藏:0   阅读:475

本文参考《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

      ----ProcessState.cpp

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类图如下:

bubuko.com,布布扣


         BpBinder代理对象被保存在BpRefBase类的成员变量mRemote中。

Android Binder进程间通信---ServiceManager代理对象的获取过程,布布扣,bubuko.com

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!