本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接
上一篇博客分析了Binder 系统架构,本篇就binder机制的重要函数调用流程进行分析:
- 1)客户端或者服务端获得servicemananger的IBinder指针的函数调用流程
- 2)客户端获得IBinder指针的函数调用流程
- 3)客户端和服务端通信的函数调用流程,了解该调用流程可对binder通信的数据流动有一个清晰的认识
获得servicemananger的IBinder指针的函数调用流程
客户端或者服务端一般会先获得servicemananger的代理,再使用该代理来查询服务或者添加服务,获得代理之前得先获得servicemananger的IBinder指针,获得IBinder指针的函数调用流程图如下图所示:
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指针的函数调用流程如下所示:(如看不清请点击看大图)
客户端一般会先获得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的子类里。
客户端和服务端通信的函数调用流程
客户端和服务端通信的函数调用流程如下图所示:(如看不清请点击看大图)
客户端进程调用接口方法时,最后会都会调用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转调不同的接口方法。