003——本地Binder框架通信原理

http://www.cloudchou.com/android/post-534.html

上一篇博客分析了Binder 系统架构,本篇就binder机制的重要函数调用流程进行分析:

  • 1) 客户端或者服务端获得servicemananger的IBinder指针的函数调用流程
  • 2) 客户端获得IBinder指针的函数调用流程
  • 3) 客户端和服务端通信的函数调用流程,了解该调用流程可对binder通信的数据流动有一个清晰的认识

获得servicemananger的IBinder指针的函数调用流程

客户端或者服务端一般会先获得servicemananger的代理,再使用该代理来查询服务或者添加服务,获得代理之前得先获得servicemananger的IBinder指针,获得IBinder指针的函数调用流程图如下图所示:

servicemananger_ibiner

interface_cast是Binder本地框架提供的一个宏函数,这里展开后得到的代码如下所示:

1
2
3
4
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
    return IServiceManager::asInterface(obj);
}

在IServiceManager.cpp里使用宏IMPLEMENT_META_INTERFACE实现了IServiceManager::asInterface函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
android::sp<IServiceManager> IServiceManager::asInterface(              
            const android::sp<android::IBinder>& obj)                 
    {                                                                  
        android::sp<IServiceManager> intr;                        
        if (obj != 0) {                                           
            intr = static_cast<IServiceManager*>(                   
                obj->queryLocalInterface(                       
                        IServiceManager::descriptor).get());     
            if (intr == 0) {                                    
                intr = new BpServiceManager(obj);               
            }                                              
        }                                                
        return intr;                                
    }

由此可知defaultServiceManager返回的IServiceManager指针指向的真实类型其实是BpServiceManager,并且封装了一个IBinder指针,这里我们主要关注IServiceManager的IBinder指针是如何获得的。

根据上图,我们可知道通过调用ProcessState::self()->getContextObject(NULL)来获得IServiceManager的IBinder指针,然后调用了getStrongProxyForHandle(0)来获得IBinder指针,由此可以知道handle为0表示servicemanager的引用。

客户端获得IBinder指针的函数调用流程

客户获得IBinder指针的函数调用流程如下所示:(如看不清请点击看大图)

client_ibinder

客户端一般会先获得IServiceManager的指针,然后通过该指针获取某个服务的IBinder指针。

示意图里的sm的真正类型其实是BpServiceManager,所以执行sm的getService方法其实是执行BpServiceManager的getService方法,BpServiceMananger的getService方法通过调用checkService方法来获得IBinder指针。

checkService方法里首先调用remote()->transact方法与servicemananger通信,获得parcel类型的返回数据。remote()的类型是IBinder指针,但指向的真实类型其实是BpBinder,它封装的handle值为0,表示servicemananger的引用。reply.readStrongBinder()的reply对象类型是parcel。

BpBinder的transact方法会转调IPCThreadState的transact方法,在IPCThreadState的transact方法里会先调用writeTransactionData填充要发送给servicemanager进程的数据,然后调用waitForResponse,waitForResponse会调用talkWithDriver将要发送的数据发给servicemananager进程,这部分数据里有要使用的service的名字,然后会收到servicemananger返回的数据,再调用parcel类型的ipcSetDataReference方法将收到的数据传给reply对象。

reply对象调用readStrongBinder以获得IBinder指针,如上图所示,会利用从servicemananger返回的handle建立BpBinder,故此客户端获得的IBinder指针指向的真实类型其实是BpBinder,客户端会将IBinder指针封装到实现了binder服务接口的BpInterface的子类里。

客户端和服务端通信的函数调用流程

客户端和服务端通信的函数调用流程如下图所示:(如看不清请点击看大图)

clientserver

客户端进程调用接口方法时,最后会都会调用remote()->transact函数提交数据到服务端进程,remote()的类型是IBinder指针,指向的实际类型其实是BpBinder(BpBinder封装了binder实体对象的句柄)。执行BpBinder的transact方法时,会调用IPCThreadState::self()->transact,先前也说到IPCThreadState负责和驱动交互数据,这里它会先调用writeTransactionData方法填充要发送给服务端进程的数据,然后调用waitForResponse方法,而waitForResponse方法会先调用talkWithDriver,talkWithDriver最终会调用ioctl方法和驱动交互,提交数据,并返回服务端进程执行的结果,然后waitForResponse方法会将收到的数据设置到reply对象里,reply为parcel类型对象。

服务端进程一般会调用joinThreadPool函数来等待客户端调用,joinThreadPool函数会先调用talkWithDriver来和驱动交互,最终调用ioctl来等待驱动提交请求,收到请求后会调用executeCommand函数,在executeCommand函数里找到BBinder对象,并执行BBinder的transact方法,BBinder的transact方法会调用它留给子类扩展的onTransact方法,BBinder子类BnInterface的子类会实现onTransact方法,根据不同的请求code转调不同的接口方法。

id="uyan_ifr_8035268" scrolling="no" frameborder="0" src="http://api.v2.uyan.cc/v4/comment/?uid=1832578&frameid=8035268&du=&su=www.cloudchou.com%2F%3Fp%3D534&pic=http%3A%2F%2Fwww.cloudchou.com%2Fwp-content%2Fuploads%2F2014%2F05%2Fservicemananger_ibiner.jpg&url=http%3A%2F%2Fwww.cloudchou.com%2Fandroid%2Fpost-534.html&title=%E6%9C%AC%E5%9C%B0Binder%E6%A1%86%E6%9E%B6%E9%80%9A%E4%BF%A1%E5%8E%9F%E7%90%86%20-%20Cloud%20Chou%27s%20Tech%20Blog&t=1477380180176" style="height: 595px; width: 626px; display: block !important; border-width: 0px !important; border-style: none !important; overflow: hidden !important;">



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值