现在的位置: 首页 > 综合 > 正文

实例分析android中的Binder通信机制(2)

2013年06月21日 ⁄ 综合 ⁄ 共 3519字 ⁄ 字号 评论关闭

    一、首先分析一下ServiceManager内容:ServiceManager提供的业务函数主要是4种:

    getServie();

    checkService() ;

    addService();

    listServices().

    已经知道,ServiceManager和Server在不同的两个进程中,所以两者之间的通信便会使用binder进行。ServiceManager和Server的关系是ServiceManager是服务端,

Server是客户端,两者之间的业务是Server端首先会向ServiceManager中注册具体的Services,这时沟通要靠binder了。

   在这里应该注意的是binder在驱动上对应着一个binder驱动设备,这个binder驱动会在内存上划分出一块共享内存块,实现数据的交互。

   现在说说MediaPlayerService这项具体的服务是如何完成在ServiceManager中的注册,binder是如何工作的。在这里还是要注意的是理解binder在业务层上的运用。

    在MediaPlayerService.cpp中首先MediaPlayerService要得到这个BpServiceManager对象,使用它才能调用addservice()完成注册。在MediaPlayerService的init函数中

实现:void MediaPlayerService::instantiate(){

          defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());

        //这个函数体描述:status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);这个remote()的返回值是BpBinder,这里就是用BpBinder代理工作

        这里,已经进入到通信层中的Binder了,这时候就是BpBinder和BBinder的正式工作了。

         }

       其实业务层用这条语句已经完成了注册任务,表面的工作已经完成,但是要理解的是真正的Binder的BpBinder和BBinder是如何工作的。在这里,MediaPlayerService的是IServiceManager.cpp中得到BpServiceManager,对于MediaPlayerService这个客户来说这时工作已经完成。剩下的就是这个BpServiceManager和BnServiceManager的工作。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         总结:

       (1)调用BpServiceManager中的addService()函数,这个是业务层的函数。

       (2)在 addService()函数这个业务的函数中把客户端的请求打包成数据包data,然后传给BpBinder的transact()函数,注意!在这里就表示把业务层 的此项通信工作 交给了BpBinder。                                    

     

二、现在一步步分析交给binder之后,binder是如何工作的:分析binder通信层的工作

   从BpBinder.cpp入手

   这个文件中主要玩儿的就是这个transact()函数,追踪这个函数之后是这个函数中的IPCThreadState()工作线程对象的transact()工作

   IPCThreadState()::self() -> transact()(在同一个类中,成员函数之间可是相互调用)IPCThreadState()::self() 会创建new出来一个IPCThreadState对象。(IPCThreadState对象会把它自己放到TLS。)

  这个对象中有两项要使用的:成员变量mIn,mOut,mIn是用来接收binder设备中的数据,mOut是用来传输数据给binder设备。第二个就是这个transact()函数的工作。

 IPCThreadState()::transact()的工作步骤:

 第一步:使用writeTransactionData(BC_TRANSACTION,flags,handle,code,data,NULL)完成把数据发出去的作用。

             
BC_TRANSACTION
:这个参数必须解释下:表示向Binder驱动设备发送要求,定义如下

                   BC_TRANSACTION = _IOW_BAD('c', 0, struct binder_transaction_data),"C"表示向驱动发请求,“0”是对应的目的端handle值,接着是需要发送的数据。

  这里会使用一个用于和binder驱动设备沟通的数据结构:struct  binder_transaction_data,这个结构体类型的变量的成员变量中,

  :

  :

 binder_transaction_data tr;

   tr.target.handle = handle; //!!这个handle的值传给target,用这个来标示目标端,在这里,0是binder系统中表示ServiceManager,这里它就是我们要的目的端

   tr.code = code;

   tr.flags = binderFlags;

 :

 :

  第二步:就是等待回复,status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)这个函数开始工作,

    函数中的重要点是switch()语句中的executeCommand()完成了接收回复的工作。在程序中以BR_FAILED_REPLY,“RB”这样的形式表示完成接收回复。

  

    主要的都有了现在要知道的就是和binder驱动设备交互的是谁,答案是:status_t IPCThreadState::talkWithDriver(bool doReceive)这个函数在工作的时候是

     binder_write_read bwr用来和binder设备交互数据结构。

     到此算是基本上找到头了!可以暂时结束一下这里的追踪工作。

 

    一个Bp####中的参数必须有BpBinder,因为这才是本质用来工作的。

 

三、关于startThreadPool和joinThreadPool的工作:

  这两者是和Binder驱动设备打交道的,startThreadPool创建新的IPCProcessState(),这个是可以用来不断工作的,同时通过joinThreadPool来读取binder设备,

  判断是否有请求存在。

 这里的一个问题是,主线程和工作线程都是可以调用startThreadPool和joinThreadPool工作的,就是一个多线程操作了。

 

  

抱歉!评论已关闭.