Binder c++代码
来源:互联网 发布:淘宝猪哼少是正品吗 编辑:程序博客网 时间:2024/04/29 07:53
这篇博客主要看一下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;}
最后我们看看客户端如何通过binder跨进程通信,调用接口。
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原理。
- Binder c++代码
- binder驱动代码注释下
- binder
- binder
- binder
- Binder
- binder
- binder
- Binder
- binder
- binder
- Binder
- Binder
- Binder
- binder
- Binder
- Binder
- Binder
- 关于 java.util.concurrent 您不知道的 5 件事,第 1 部分
- @Override的意思
- Mybatis如何获取不知道确定字段的所有数据
- bootstrap的学习和资料
- SAP HR模块复制PA30的人员
- Binder c++代码
- java编程中的异常总结(一)
- 应用程序初始化(0xc000007b)失败,请点击确认后关闭应用程序
- 人脸表情识别相关研究
- SAP WM模块常用T-code
- 解决ORACLE用expdp导出时,输出日志的内容不完整问题
- word 编号值与后面的文本之间的空隙大怎么处理
- 设计模式之禅--------策略模式
- 低延迟系统的 11 个最佳实践