本文拜读参考自罗升杨老师的 《Android系统源代码情景分析》
概述:
Android系统在应用程序框架中将各种Binder驱动程序操作封装成一个Binder库,这样进程就可以方便的调用Binder库提供的接口来实现进程间通信。在Binder库中,Service组件和Client组件分别使用模板类BnInterface和BpInterface来描述,其中,前者成为Binder本地对象,后者称为Binder代理对象。Binder库中的Binder本地对象和Binder代理对象分别对象与Binder驱动程序中的 Binder实体对象和Binder引用对象。以下是两个模板的介绍。
一 模板类BnInterface和BpInterface的定义
模板类BnInterface和BpInterface的定义如下。
frameworks\native\include\binder\IInterface.h
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();
};
// ----------------------------------------------------------------------
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
参数模板 INTERFACE 是一个由进程自定义的 Service 组件接口,模板类 BnInterface 和 BpInterface 都需要实现该接口。在使用 Binder 库开发 Service 组件和 Client 组件时,除了要定义 Service 组件接口之外,还必须要实现一个 Binder 本地对象类和一个 Binder代理对象类,他们分别继承于末模板类 BnInterface 和
BpInterface。
二 模板类 BnInterface
模板类 BnInterface 继承了 BBinder类,后者为 Binder本地对象 提供了抽象的进程间通信接口,定义如下
frameworks\native\include\binder\Binder.h
class BBinder : public IBinder
{
.......
/*
* 当一个Binder代理对象通过Binder驱动程序向一个Binder本地对象发出一个进程间通信请求时,Binder驱动程序就会调用
* 该Binde本地对象的成员函数 transact 来处请求。
*
*/
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
......
protected:
virtual ~BBinder();
/*
* 成员函数 onTransact 是虚函数,它是由 BBinder 的子类,即 Binder本地对象类来实现的,他负责分发与业务相关的进程间通
* 信请求。事实上,与业务相关的进程间通信请求是由Binder本地对象类的子类,即Service组件来负责处理的。
*/
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0) ;
.....
};
BBinder类有两个重要的成员函数 transact 和 onTransact。当一个Binder代理对象通过Binder驱动程序向一个Binder本地对象发出一个进程间通信请求时,Binder驱动程序就会调用该Binde本地对象的成员函数 transact 来处请求。成员函数 onTransact 是虚函数,它是由 BBinder 的子类,即 Binder本地对象类来实现的,他负责分发与业务相关的进程间通信请求。事实上,与业务相关的进程间通信请求是由Binder本地对象类的子类,即Service组件来负责处理的。
BBinder 类继承自 IBinder类,IBinder类又继承自 RefBase类。继承了RefBase类的子类的对象均可以通过请指针和弱指针来维护他们的生命周期,也就是说,就是Binder本地对象是通过引用计数技术来维护生命周期的。Binder本地对象受到Binder驱动程序中的Binder实体对象以及运行在Client进程中的Binder代理对象引用。
三 模板类 BpInterface
模板类 BpInterface 继承自 BpRefBase 类,后者为 Binder代理对象 提供了抽象的进程间通信接口,定义如下:
frameworks\native\include\binder\Binder.h
class BpRefBase : public virtual RefBase
{
protected:
BpRefBase(const sp<IBinder>& o);
......
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
......
IBinder* const mRemote; //它指向一个 BpBinder对象
......
};
}; // namespace android
BpRefBase类有继承自 RefBase类,所以他的子类对象,即 Binde代理对象也可以通过强指针和弱指针来维护维护声明周期。RefBase类中成员变量 mRemote,它指向一个 BpBinder对象,可以通过成员函数 remote来获取。 BpBinder类实现了 BpRefBase类的进程间通信接口,如下:
class BpBinder : public IBinder
{
public:
BpBinder(int32_t handle);
inline int32_t handle() const { return mHandle; }//获取Client组件的句柄值
......
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
......
private:
const int32_t mHandle;//表示一个Client组件的句柄值
......
};
BpBinder 类的成员变量 mHandle 是一个整数,它表示一个Client组件的句柄值,可以通过成员函数 handle() 来获取。成员函数 transact 用来向运行在 Service 进程中的 Service 组件发送进程间通信请求,这是通过 Binder驱动程序间接实现的。BpBinder类的成员函数 transact 会把 BpBinder类的成员变量 mHandle,以及进程间通信数据发送给 Binder驱动程序,这样Binder 驱动程序就能根据这个句柄值来找到对应的 Binder引用对象,继而找到对应的的Binder实体对象,最后就可以将进程间通信数据发送给对应的Service 组件了。
小结:
class BpRefBase : public virtual RefBase // RefBase类的子类对象可以通过强指针和弱指针来维护维护声明周期。
BpRefBase.mRemote ->public BpBinder.transact 向运行在 Service 进程中的 Service 组件发送进程间通信请求
class BpInterface :public BpRefBase
三 IPCThreadState类
无论是 BBinder类,还是 BpBinder 类,他们都是通过 IPCThreadState类来和Binder驱动程序交互的。
class IPCThreadState
{
public:
static IPCThreadState* self();
......
status_t transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
......
private:
......
status_t talkWithDriver(bool doReceive=true);
......
const sp<ProcessState> mProcess;
......
};
每一个使用了Binder 进程间通信机制的进程都有一个 Binder线程池,用来处理进程间通信请求。对于每一个Binder线程来说,它的内部都有一个 IPCThreadState 对象,我们可以通过 IPCThreadState类的静态成员函数 self() 来获取,并且调用成员函数 transact()来与 Binder 驱动程序交互。在 IPCThreadState 类的静态成员函数 transact 内部,与Binder驱动程序的交互操作又是通过调用成员函数 talkWithDriver() 来实现的,它一方面负责向 Binder 驱动程序发送进程间通信请求,另一方面又负责接收来自 Binder 驱动程序的进程间通信请求。IPCThreadState类的成员变量 mProcess,他指向一个 ProcessState对象,对于每一个使用了 Binder 进程间通信机制的进程来说,它内部都有一个ProcessState对象,他负责初始化Binder设备。即打开设备文件 /dev/binder,以及将设备 /dev/binder 映射到进程的地址空间,由于这个 ProcessState对象在进程范围内是唯一的,所以,Binder线程池中的每一个线程都可以通过它来和Binder驱动建立连接。
class ProcessState : public virtual RefBase{
public:
static sp<ProcessState> self();
......
private:
......
int mDriverFD;
void* mVMStart;
......
};
进程中的 ProcessState 对象可以通过 成员函数 self()来获取。调用 self() ,Binder库就会为进程创建一个 ProcessState 对象,并且调用函数 open 来打开设备文件 /dev/binder,接着又调用函数 mmap()将它映射到进程的地址空间,即请求Binder驱动程序为进程分配内核缓冲区。设备文件 /dev/binder 映射到进程的地址空间后,得到的内核缓冲区的用户地址就保存在其成员变量 mVMStart中。
ProcessState 分析
sp<ProcessState> proc(ProcessState::self())
1
//self函数采用单例模式,即每个进程只有一个 ProcessState对象。
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
//gProcess是一个全局变量,程序刚开始执行,gProcess一定为空。
if (gProcess != NULL) {
return gProcess;
}
//创建一个 ProcessState 对象,并赋值给 gProcess
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
2 ProcessState的构造
frameworks/native/libs/binder/ProcessState.cpp
static int open_driver()
{
//dakai Binder设备
int fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
//ioctl 查询版本号
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
//ioctl 确认最大线程数 :15
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
//ProcessState的构造函数
ProcessState::ProcessState()
: mDriverFD(open_driver()) // 打开 Binder 设备
, mVMStart(MAP_FAILED)//映射内存起始地址
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}