这篇博客主要看一下binder的一些实现,以及自己写一个实例:
Binder中service组件和client组件分别使用模板类BnInterface和BpInterface来描述,前者为Binder的本地对象,后者为代理对象。
// ---------------------------------------------------------------------- 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是一个由进程自定义的的接口,Bninterface和BpInterface都需要实现该接口,自己必须实现Bninterface和BpInterface这两个类
下面是自己实现的一个.h文件
class IExampleService : public IInterface { public: DECLARE_META_INTERFACE(ExampleSercie); virtual int get () = 0; virtual void set (int value) = 0; } class BnExampleService : public BnInterface<IExampleService>//这边的模板其实对应上面的定义,就是继承这个接口类而已 { virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); }对应实现一个.cpp文件,Bp和Bn的实现在一个文件中,但是实际上是在两个进程中,两个类都要实现IExampleService中的方法
enum { EXAMPLE_GET = IBinder::FIRST_CALL_TRANSACTION, EXAMPLE_SET, }; class BpExampleService : public BpInterface<IExampleService> { public: virtual int get() { Parcel data, reply; data.writeInterfaceToken(IExampleService::getInterfaceDescriptor()); remote()->transact(EXAMPLE_GET, data, &reply); return reply.readInt(); } virtual void set(int value) { Parcel data, reply; data.writeInterfaceToken(IExampleService::getInterfaceDescriptor()); data.writeInt(value); remote()->transact(EXAMPLE_SET, data, &reply); return; } }; IMPLEMENT_META_INTERFACE(ExampleService, "ExampleDescriptor"); status_t BnExampleService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case EXAMPLE_GET: CHECK_INTERFACE(IExampleService, data, &reply); reply->writeInt(get()); break; case EXAMPLE_SET: CHECK_INTERFACE(IExampleService, data, &reply); set(data->readInt()); break; default: return BBinder::onTransact(code,data,reply,flags); } return NO_ERROR; }
最后实现service,ExampleService需要继承BnExampleService,并实现虚函数,添加一个instantiate函数将当前service加入到servicemanager中。
class ExampleService : pulic BnExampleService { public: ExampleService ():mValue(0); public int get() {return mValue}; public void set (int value) { mValue = value;} public static void instantiate() { defaultServiceManager()->addService(String16("example"), new ExampleService()); } private: int mValue; }
Bninterface类继承了BBinder,定义如下:
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); ...... };
当有一个Binder代理对象(客户端)通过binder驱动程序向一个binder本地对象(server端)发出一个进程间通信请求时,Binder驱动程序就会调用该Binder本地对象的成员函数tracsact来处理该请求。onTransact由子类实现,负责分发与业务相关的进程间通信请求,我们的例子中在BnExampleService实现了该函数,负责处理进程间发送过来的请求。
class BpRefBase : public virtual RefBase { protected: BpRefBase(const sp<IBinder>& o); virtual ~BpRefBase(); ........ inline IBinder* remote() { return mRemote; } inline IBinder* remote() const { return mRemote; } private: ........ IBinder* const mRemote; ...... };
mRemote指向一个BpBinder对象,可以通过remote函数来获取
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函数获取,它是binder驱动程序中一个client的binder引用对象,client组件通过这个句柄和binder对象引用对象建立对应关系。
BpBinder类的transact用来向运行在server进程中的service组件发送进程间通信请求,通过binder驱动实现。transact会把mHandle,以及通信数据发送给binder驱动,这样驱动可以根据这个句柄值找到对应的binder引用对象,然后找到binder实体对象,最后把通信数据发给对应的service组件。
无论是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线程,内部都有一个IPCThreaState对象,可以通过self获取,transact函数和binder驱动交互,在transact函数内部调用talkwithDriver来实现,它一方面负责向binder驱动发送通信请求,一方面接受binder驱动通信请求。
IPCThreadState类有一个mProcess,指向ProcessState对象。对于每个使用binder的进程,内部都有一个ProcessState对象,负责初始化Binder设备,即打开设备文件/dev/binder,以及将设备文件/dev/binder映射到进程的地址空间。由于ProcessState对象在进程唯一,binder线程池中每一线程都可以通过它与驱动程序连接。
class ProcessState : public virtual RefBase { public: static sp<ProcessState> self(); .... private: int mDriverFD; void* mVMStart; .... };
进程中可以通过self函数获取ProcessState 对象,第一次调用创建一个对象,并且打开设备文件/dev/binder, 然后调用函数mmap将它映射到进程的地址空间,即请求binder驱动为进程分配内核缓冲区。得到的内核缓冲区的用户地址保存在mVMStart中。
前面实例中有两个宏还没有分析
#define DECLARE_META_INTERFACE(INTERFACE) \ static const android::String16 descriptor; \ static android::sp<I##INTERFACE> asInterface( \ const android::sp<android::IBinder>& obj); \ virtual const android::String16& getInterfaceDescriptor() const; \ I##INTERFACE(); \ virtual ~I##INTERFACE(); \ #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ const android::String16 I##INTERFACE::descriptor(NAME); \ const android::String16& \ I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ } \ android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ const android::sp<android::IBinder>& obj) \ { \ android::sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \ I##INTERFACE::I##INTERFACE() { } \ I##INTERFACE::~I##INTERFACE() { }
其中就是实现自己的IExample一些固定接口,这边主要看下asInterface这个函数,IBinder中有两个接口,localBinder,remoteBinder,localBinder指的是Binder实体对象,remoteBInder指的是引用对象。
对于服务进程,localBinder有意义,remoteBinder没有意义。在客户端就相反,remoteBinder有意义。因此在asInterface中,querLocalInterface返回为空代表是在客户端,因此需要new Bp##INTERFACE对象。即BpBinder没有重载querLocalInterface这函数,返回为null
下面我们实现service进程的主函数。
int main() { ExampleService::instantiate();//将service加入到serviceManager中 processState::self()->startThreadPool();//开启了一个线程读取binder请求 IPCThreadState::self()->joinThreadPool();//主线程joinThreadPool读取binder请求,因此有两个binder线程。 return 0; }
int main() { sp<IBinder> binder = defaultServiceManager()->getService(string16("example")); if (binder == null) { LOGE("failed"); return -1; } sp<IExampleService> service = IExampleService::asInterface(binder);//将IBinder转换成 int value = service->get(); printf("%d", value); }binder c++的分析完了,后面分析下java的binder原理。