openharmony 中存在很多的服务,一般来说可以使得 a 应用调用 b 服务的方法,就像在自己进程中调用一样,这里具体的实现实际通过 binder 驱动实现。
binder 驱动通过 mmap 将内核态代码映射到用户态,直接读写数据这样就完成了跨进程的调用。不过这不是该篇内容的重点,本片主要讲一下 proxy - stub 的设计模式。
服务的一般编码模式
使用 proxy - stub 架构编程,大致可以分为以下三个步骤:
设计接口类,继承至 iremotebroker,接口方法一般设计为虚方法。
设计 proxy 类,继承至 iremoteproxy,并且实现 sendrequest 方法和自身虚方法。
设计 stub 类,继承至 iremotestub ,并且实现 onremote 方法和自身虚方法。
这样我们就可以在调用是调用 proxy 类的接口方法就像调用 stub 类的接口方法一样了。
源码剖析
我们通过阅读源码,解开其神秘的面纱。我们现在关注几个重点的类。
iremoteobject:
class iremoteobject : public virtual parcelable, public virtual refbase {public: enum { if_prot_default, /* invoker family. */ if_prot_binder = if_prot_default, if_prot_databus, }; enum { databus_type, }; class deathrecipient : public refbase { public: enum { add_death_recipient, remove_death_recipient, notice_death_recipient, test_service_death_recipient, test_device_death_recipient, }; virtual void onremotedied(const wptr &object) = 0; }; virtual int32_t getobjectrefcount() = 0; virtual int sendrequest(uint32_t code, messageparcel &data, messageparcel &reply, messageoption &option) = 0; virtual bool isproxyobject() const; virtual bool checkobjectlegality() const; virtual bool adddeathrecipient(const sptr &recipient) = 0; virtual bool removedeathrecipient(const sptr &recipient) = 0; virtual bool marshalling(parcel &parcel) const override; static iremoteobject *unmarshalling(parcel &parcel); static bool marshalling(parcel &parcel, const sptr &object); virtual sptr asinterface(); virtual int dump(int fd, const std::vector &args) = 0; const std::u16string descriptor_; std::u16string getobjectdescriptor() const;protected: explicit iremoteobject(std::u16string descriptor = nullptr);};
这就是真正在 binder 驱动中数据传输的类,继承自 parcelable 。而继承refbase 可以理解为智能指针的控制块。
openharmony 中这里并没有直接使用 c++ 标准库中的智能指针,而是使用 sptr 和 refbase 两个类共同构建,也就是裸指针和控制块相关信息。使用后者的方式,更加解耦。符合复杂架构设计理念。
iremotebroker:
class iremotebroker : public virtual refbase {public: iremotebroker() = default; virtual ~iremotebroker() override = default; virtual sptr asobject() = 0; static inline sptr asimplement(const sptr &object) { return nullptr; }};#define declare_interface_descriptor(descriptor) static inline const std::u16string metadescriptor_ = { descriptor }; static inline const std::u16string &getdescriptor() { return metadescriptor_; }
一般的接口类,通过 metadescriptor_ 作为表示区分标识。
iremoteproxy:
namespace ohos {template class iremoteproxy : public peerholder, public interface {public: explicit iremoteproxy(const sptr &object); ~iremoteproxy() override = default;protected: sptr asobject() override;};template iremoteproxy::iremoteproxy(const sptr &object) : peerholder(object){}template sptr iremoteproxy::asobject(){ return remote();}} // namespace ohos
iremoteproxy 使用 c++ 的 crtp (奇特重现模板模式)编程,使得父类可以调用子类的方法。继承自 peerhold (其实就是包括一个 iremoteobject 对象)。
iremotestub:
namespace ohos {template class iremotestub : public ipcobjectstub, public interface {public: iremotestub(); virtual ~iremotestub() = default; sptr asobject() override; sptr asinterface() override;};template iremotestub::iremotestub() : ipcobjectstub(interface::getdescriptor()) {}template sptr iremotestub::asinterface(){ return this;}template sptr iremotestub::asobject(){ return this;}} // namespace ohos
stub 对象较于 proxy 对象复杂一些,也使用 crtp 编程。会继承 ipcobjectstub(也是 iremoteobject 对象)。
看到这里,可能有人疑惑,为什么 proxy 调用,会直接调用到 stub 这端呢?
其实奥秘就在于 stub 继承的 ipcobjectstub(继承 iremoteobject)对象,就是这个 iremoteobject 对象。
proxy 的构造继承 peerhold,peerhold 类中的iremoteobject 对象和 ipcobjectstub 这个是什么关系呢?
其实 peerhold 是 ipcobjectstub 的引用对象,实际类型是 ipcobjectproxy。
这两者在 ipc 框架中,ipcobjectproxy 实际使用 sendrequest,ipcobjectstub 便会调用 onremoterequest。如果有兴趣,我们下次可以分析 ipc 框架具体是如何实现的。
原文标题:剖析鸿蒙经典的proxy - stub架构
文章出处:【微信公众号:harmonyos技术社区】欢迎添加关注!文章转载请注明出处。
大唐电信拟筹资25亿元收购联芯科技等三公司
马云:企业家要有敬畏之心,AI区块链—你想要的,时代都会给你
亚马逊宣布再雇用10万名员工 并计划优先运送医疗用品和家庭必需品
动态内存分配优化了Blackfin处理器软件的集成
IC企业的成长基础是技术、是研发、是人才
详解proxy-stub结构的设计模式
科大讯飞正式推出新一代智能办公本X2
dfrobotMicro USB数据线简介
华为新的泄漏揭示了即将推出的智能手表的细节
GNSS模块供应商有哪些?
iPhone8、三星Note8最新消息汇总:iPhone8、三星Note8不拼性能拼价格,超8000你买谁?
电子复合功能材料在智能手机中的应用
【蓝桥杯物联网】第三章 stm32l0xx_hal_gpio.c的常见函数
L9942反电动势堵转检测算法
哪款蓝牙耳机颜值比较高?四款音质好的蓝牙耳机测评
企业微信对接CRM销售系统,助力企业客户增长
5G开启万物智能互联时代 首个商用5G智慧电网在广东启动
艺术品般的美军“军刀”对讲机的拆解(多图详细)
浅谈采煤机电动机故障保护装置的改进措施
人工智能时代新闻行业还能坚持多久