源碼分析—解析Proxy - Stub 架構的奧秘
服務概覽
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<IRemoteObject> &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<DeathRecipient> &recipient) = 0;
virtual bool RemoveDeathRecipient(const sptr<DeathRecipient> &recipient) = 0;
virtual bool Marshalling(Parcel &parcel) const override;
static IRemoteObject *Unmarshalling(Parcel &parcel);
static bool Marshalling(Parcel &parcel, const sptr<IRemoteObject> &object);
virtual sptr<IRemoteBroker> AsInterface();
virtual int Dump(int fd, const std::vector<std::u16string> &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<IRemoteObject> AsObject() = 0;
static inline sptr<IRemoteBroker> AsImplement(const sptr<IRemoteObject> &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 <typename INTERFACE> class IRemoteProxy : public PeerHolder, public INTERFACE {
public:
explicit IRemoteProxy(const sptr<IRemoteObject> &object);
~IRemoteProxy() override = default;
protected:
sptr<IRemoteObject> AsObject() override;
};
template <typename INTERFACE>
IRemoteProxy<INTERFACE>::IRemoteProxy(const sptr<IRemoteObject> &object) : PeerHolder(object)
{
}
template <typename INTERFACE> sptr<IRemoteObject> IRemoteProxy<INTERFACE>::AsObject()
{
return Remote();
}
} // namespace OHOS
IRemoteProxy 使用c++的crtp (奇特重現模板模式)編程,使得父類可以調用子類的方法。繼承自peerhold (其實就是包括一個IRemoteObject對象) 。
IRemoteStub:
namespace OHOS {
template <typename INTERFACE> class IRemoteStub : public IPCObjectStub, public INTERFACE {
public:
IRemoteStub();
virtual ~IRemoteStub() = default;
sptr<IRemoteObject> AsObject() override;
sptr<IRemoteBroker> AsInterface() override;
};
template <typename INTERFACE> IRemoteStub<INTERFACE>::IRemoteStub() : IPCObjectStub(INTERFACE::GetDescriptor()) {}
template <typename INTERFACE> sptr<IRemoteBroker> IRemoteStub<INTERFACE>::AsInterface()
{
return this;
}
template <typename INTERFACE> sptr<IRemoteObject> IRemoteStub<INTERFACE>::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框架具體是如何實現的。