安卓源码解析:Binder进程间通讯机制(4)-内核空间Binder驱动详解(Binder驱动库 C/C++接口简介)
目录
- Binder进程间通讯机制(1)-简况
- Binder进程间通讯机制(2)-内核空间Binder驱动详解(基础数据结构)
- Binder进程间通讯机制(3)-内核空间Binder驱动详解(Binder驱动内存管理)
- Binder进程间通讯机制(4)-内核空间Binder驱动详解(Binder驱动库 C/C++接口简介)
- Binder进程间通讯机制(5)-从ServiceManager的角度分析IPC原理
Binder由Service组件和Client组件组成,两个组件通过Binder内核进行通信,Service组件继承BnInterface,包含BnXXXX开头的所有类,Service组件被称为本地对象对应Binder驱动实体对象,Client组件被称为代理对象对应BInder驱动中的引用对象.中的最终功能的实现是继承了BnXXXX的Service类,数据通过IPCThreadState和ProcessState进行向Binder内核通讯.
Service的结构图如下:
- BnInterface继承IXXXX以及BBinder
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
INTERFACE
为进程自定义的Service组件接口,Client和Service组件都会继承这个接口,并实现里面的方法.Service组件具体的实现会定义在XXXX
类中.Service端除了要实现接口还需要实现一个Binder本地对象BnXXXX
.
- 具体实现类XXXX
比如BServiceManager
,里面定义了从ServiceManger中获取Service组件getService
,以及Client组件向Service组件注册组件setService
的具体实现.
status_t BServiceManager::addService(const String16& name, const sp<IBinder>& service)
{
AutoMutex _l(mLock);
LOGI("ServiceManager: addService(%s, %p)\n", String8(name).string(), service.get());
const ssize_t res = mServices.add(name, service);
if (res >= NO_ERROR) {
mChanged.broadcast();
return NO_ERROR;
}
return res;
}
sp<IBinder> BServiceManager::getService(const String16& name) const
{
AutoMutex _l(mLock);
ssize_t i = mServices.indexOfKey(name);
LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i);
if (i >= 0) return mServices.valueAt(i);
return NULL;
}
- BnXXXX
例如 ServiceManager组件
的本地对象BnServiceManager
用来定义onTransct
方法接收binder传递的指令判断后分发给实现类ServiceManager的两个方法.
status_t BnServiceManager::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case ADD_SERVICE_TRANSACTION: {
//添加Service
CHECK_INTERFACE(IServiceManager, data, reply);
String16 which = data.readString16();
sp<IBinder> b = data.readStrongBinder();
status_t err = addService(which, b);
reply->writeInt32(err);
return NO_ERROR;
} break;
}
}
};
//虚函数addService 被BServiceManager实现
virtual status_t addService(const String16& name, const sp<IBinder>& service)
{
....
}
BServiceManager的addService
status_t BServiceManager::addService(const String16& name, const sp<IBinder>& service)
{
AutoMutex _l(mLock);
LOGI("ServiceManager: addService(%s, %p)\n", String8(name).string(), service.get());
//将Service组件注册到mService集合中
const ssize_t res = mServices.add(name, service);
if (res >= NO_ERROR) {
mChanged.broadcast();
return NO_ERROR;
}
return res;
}
- BBinder
BnInterface继承了BBinder,在Service组件中,BBinder定义重要的函数onTransact
,当Binder代理对象通过Binder驱动程序向一个Binder本地对象发送一个进程间通讯请求时,Binder驱动会调用transact
方法进行请求,调用onTransact
方法分发与业务相关的请求.其实onTransact会被BBinder的子类,例如BnServiceManager
进行实现,会调用上面所说的BnServiceManager
的onTransact
方法.
- BnInterface
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
const String16& _descriptor)
{
if (_descriptor == INTERFACE::descriptor) return this;
return NULL;
}
BnInterface主要提供queryLocalInterface
和getInterfaceDescriptor
,第一个方法主要用来获取BnBinder本地对象,第二个方法用来获取描述这个本地对象的字符串.
- IPCThreadState
class IPCThreadState
{
public:
static IPCThreadState* self();
status_t transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
private:
const sp<ProcessState> mProcess;
};
}; // namespace android
IPCThreadState
是用来和Binder程序进程交互的,每一个Binder线程内部都有一个IPCThreadState,可以根据函数self()
获取这个对象,transact
是用来和Binder进程交互的函数,与Binder进程交互又是通过调用私有函数talkWithDriver
实现,他一方面负责发送给Binder驱动数据一方面用来接收Binder驱动发送过来的数据.
- ProcessState
每个BInder线程对应的IPCThreadState内部都有一个mProcess
成员变量对应的ProcessState
对象,他负责初始化Binder设备,负责打开设备文件/dev/binder,并将它映射到进程的地址空间,让每一个BInder线程和Binder驱动建立连接.
Client的结构图如下:
- BpXXXX
BpXXXX为Binder代理对象的具体实现类,与Binder本地对象继承同一个`IInterface,实现同样的接口,例如在
BpServiceManager`中实现了getService以及addService虚函数,当有其他进程要调用ServiceManager的时候会先获取到SM的Binder代理对象并调用他的具体方法.
//代理對象addService
virtual status_t addService(const String16& name, const sp<IBinder>& service)
{
Parcel data, reply;
//写入协议头(请求头)
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
//将要传递的Service组件封装成binder结构体
data.writeStrongBinder(service);
//调用BpBinder 的 transact方法
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
- BpRefBase
BpRefBase用来为Binder代理对象提供进程间通讯的抽象接口,其中成员变量mRemote
指向一个BpBinder
对象,可以通过方法remote()
获取.
class BpRefBase : public virtual RefBase
{
protected:
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
IBinder* const mRemote;
};
}; // namespace android
- BpBinder
BpBinder为Binder代理对象实现的进程间通讯接口,成员变量mHandle
是一个表示Client组件的句柄
,每一个Client组件在Binder驱动中都对应一个Binder引用对象,每一个Binder引用对象都有一个句柄值,client组件就是通过这个句柄值来和binder驱动中的binder引用对象建立联系.
BpBinder的transact
方法用来向service组件发送进程间通讯请求,client端会通过这个方法将句柄值发送给Binder驱动,这样binder驱动就能跟着这个句柄找到binder引用对象,继而找到binder实体对象,并将请求发送给binder实体对象所对应的service组件.
而BpBinder具体如何发送指令又是通过IPCThreadState处理的.