Android Binder
2015-07-09 18:09
633 查看
Binder进程间通信库
Android系统在应用程序框架层将各种Binder驱动程序操作封装成了一个Binder库,这样进程就可以方便调用Binder库提供的接口来进行进程间通信。在Binder库中,Service组件和Client组件分别使用模板类BnInterface和BpInterface来描述,其中,前者称为Binder本地对象(Binder Native),后者称为Binder代理对象(Binder proxy)。Binder库中的Binder本地对象和代理对象分别对应于Binder驱动程序中的Binder实体对象和Binder引用对象。下面我们主要介绍这两个模板类的实现。模板类BnInterface和BpInterface的定义如下所示:
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(); }
模板参数INTERFAE是一个由进程自定义的Service组件接口,模板类BnInterface和BpInterface都需要实现该接口。在使用Binder库开发Service组件和Client组件时,除了要定义Service组件接口之外,还必须要实现一个Binder本地对象类和一个Binder代理对象类,它们分别继承于模板类BnInterface和BpInterface。
BnInterface
模板类BnInterface继承了BBinder类,后者为Binder本地对象提供了抽象的进程间通信接口,它的定义如下所示:class BBinder : public IBinder { public: // ...... virtual status_t transact(uint32_t code, const Parcel& data, Parcel *reply, uint32_t flags = 0); // ...... protected: // ...... virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); }
BBinder类有两个重要的成员函数transact和onTransact。当一个Binder代理对象通过Binder驱动程序向一个Binder本地对象发出一个进程间通信请求时,Binder驱动程序就会调用该Binder本地对象的成员函数transact来处理该请求。成员函数onTransact是由BBinder的子类,即Binder本地对象类来实现的,它负责分发与业务相关的进程间通信请求。事实上,与业务相关的进程间通信请求是由Binder本地对象类的子类,即Service组件类来负责处理的。
BBinder类又继承了IBinder类,而后者又继承了RefBase类。由Android智能指针的知识可知,继承了RefBase类的子类的对象均可以通过强指针和弱指针来维护它们的生命周期,换句话说,就是Binder本地对象是通过引用计数技术来维护生命周期的。
BpInterface
模板类BpInterface继承自BpRefBase类,后者为Binder代理对象提供了抽象的进程间通信接口,它的定义如下所示:class BpRefBase : public virtual BpRefBase { protected: BpRefBase(const sp<IBinder>& o); virtual ~BpRefBase(); inline IBinder* remote() {return mRemote;} inline IBinder* remote() const {return mRemote;} private: IBinder* const mRemote; }
BpRefBase类又继承了RefBase类,因此,它的子类对象,即Binder代理对象也可以通过强指针和弱指针来维护生命周期。
BpRefBase类有一个重要的成员变量mRemote,它指向一个BpBinder对象,可以通过成员函数remote来获取。BpBinder类实现了BpRefBase类的进程间通信接口,它的定义如下所示。
class BpBinder : public IBinder { public: BpBinder(int32_t handle); inline int32_t handle() const { return mHandle; } virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); private: const int32_t mHandle; }
BpBinder类的成员变量mHandle是一个整数,它表示一个Client组件的句柄值,可以通过成员函数handle来获取。每一个Client组件在Binder驱动程序中都对应有一个Binder引用对象,而每一个Binder引用对象都有一个句柄值,其中,Client组件就是通过这个句柄值来和Binder驱动程序中的Binder引用对象建立对应关系的。
BpBinder类的成员函数transact用来向运行在Server进程中的Service组件发送进程间通信请求,这是通过Binder驱动程序间接实现的。BpBinder类的成员函数transact会把BpBinder类的成员变量mHandle,以及进程间通信数据发送给Binder驱动程序,这样Binder驱动程序就能根据这个句柄值来找到对应的Binder引用对象,继而找到对应的Binder实体对象,最后就可以将进程间通信数据发送给对应的Service组件了。
IPCThreadState
无论是BBinder类,还是BpBinder类,它们都是通过IPC-ThreadState类来和Binder驱动程序交互的。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: status_t talkWithDriver(bool doReceive=true); // ... const sp<ProcessState> mProcess; // ... }
每一个使用了Binder进程间通信机制的进程都有一个Binder线程池,用来处理进程间通信请求。对于每一个Binder线程来说,它的内部都有一个IPCThreadState对象,我们可以通过IPCThreadState类的静态成员函数self来获取,并且调用它的成员函数transanct来和Binder驱动程序进行交互。在IPCThreadState类的成员函数transanct内部,与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对象可以通过ProcessState类的静态成员函数self来获取。第一次调用ProcessState类的静态成员函数self时,Binder库就会为进程创建一个ProcessState对象,并且调用函数open来打开设备文件/dev/binder,接着又调用函数mmap将它映射到进程的地址空间,即请求Binder驱动程序为进程分配内核缓冲区。设备文件/dev/binder映射到进程的地址空间后,得到的内核缓冲区的用户地址就保存在其成员变量mVMStart中。
至此,Binder库的基础知识就介绍完毕了。我们通过如下两个UML图来描述Service组件和Client组件的实现原理。
IXXXXX表示Service组件和Client组件都需要实现的服务接口。BnXXXXX和BpXXXXX分别表示Service组件和Client组件要继承的Binder本地对象类和Binder代理对象类。XXXXX表示一个具体的Service组件。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories