OpenHarmony 中存在很多的服務(wù),一般來說可以使得 A 應用調(diào)用 B 服務(wù)的方法,就像在自己進程中調(diào)用一樣,這里具體的實現(xiàn)實際通過 binder 驅(qū)動實現(xiàn)。
binder 驅(qū)動通過 mmap 將內(nèi)核態(tài)代碼映射到用戶態(tài),直接讀寫數(shù)據(jù)這樣就完成了跨進程的調(diào)用。不過這不是該篇內(nèi)容的重點,本片主要講一下 proxy - stub 的設(shè)計模式。
服務(wù)的一般編碼模式
使用 proxy - stub 架構(gòu)編程,大致可以分為以下三個步驟:
設(shè)計接口類,繼承至 IRemoteBroker,接口方法一般設(shè)計為虛方法。
設(shè)計 proxy 類,繼承至 IRemoteProxy,并且實現(xiàn) sendRequest 方法和自身虛方法。
設(shè)計 stub 類,繼承至 IRemoteStub ,并且實現(xiàn) OnRemote 方法和自身虛方法。
這樣我們就可以在調(diào)用是調(diào)用 proxy 類的接口方法就像調(diào)用 stub 類的接口方法一樣了。
源碼剖析
我們通過閱讀源碼,解開其神秘的面紗。我們現(xiàn)在關(guān)注幾個重點的類。
IRemoteObject:
classIRemoteObject:publicvirtualParcelable,publicvirtualRefBase{
public:
enum{
IF_PROT_DEFAULT,/*Invokerfamily.*/
IF_PROT_BINDER=IF_PROT_DEFAULT,
IF_PROT_DATABUS,
};
enum{
DATABUS_TYPE,
};
classDeathRecipient:publicRefBase{
public:
enum{
ADD_DEATH_RECIPIENT,
REMOVE_DEATH_RECIPIENT,
NOTICE_DEATH_RECIPIENT,
TEST_SERVICE_DEATH_RECIPIENT,
TEST_DEVICE_DEATH_RECIPIENT,
};
virtualvoidOnRemoteDied(constwptr&object)=0;
};
virtualint32_tGetObjectRefCount()=0;
virtualintSendRequest(uint32_tcode,MessageParcel&data,MessageParcel&reply,MessageOption&option)=0;
virtualboolIsProxyObject()const;
virtualboolCheckObjectLegality()const;
virtualboolAddDeathRecipient(constsptr&recipient)=0;
virtualboolRemoveDeathRecipient(constsptr&recipient)=0;
virtualboolMarshalling(Parcel&parcel)constoverride;
staticIRemoteObject*Unmarshalling(Parcel&parcel);
staticboolMarshalling(Parcel&parcel,constsptr&object);
virtualsptrAsInterface();
virtualintDump(intfd,conststd::vector<std::u16string>&args)=0;
conststd::u16stringdescriptor_;
std::u16stringGetObjectDescriptor()const;
protected:
explicitIRemoteObject(std::u16stringdescriptor=nullptr);
};
這就是真正在 binder 驅(qū)動中數(shù)據(jù)傳輸?shù)念?,繼承自 Parcelable 。而繼承RefBase 可以理解為智能指針的控制塊。
OpenHarmony 中這里并沒有直接使用 C++ 標準庫中的智能指針,而是使用 sptr 和 refbase 兩個類共同構(gòu)建,也就是裸指針和控制塊相關(guān)信息。使用后者的方式,更加解耦。符合復雜架構(gòu)設(shè)計理念。
IRemoteBroker:
classIRemoteBroker:publicvirtualRefBase{
public:
IRemoteBroker()=default;
virtual~IRemoteBroker()override=default;
virtualsptrAsObject()=0;
staticinlinesptrAsImplement(constsptr&object)
{
returnnullptr;
}
};
#defineDECLARE_INTERFACE_DESCRIPTOR(DESCRIPTOR)
staticinlineconststd::u16stringmetaDescriptor_={DESCRIPTOR};
staticinlineconststd::u16string&GetDescriptor()
{
returnmetaDescriptor_;
}
一般的接口類,通過 metaDescriptor_ 作為表示區(qū)分標識。
IRemoteProxy:
namespaceOHOS{
template<typenameINTERFACE>classIRemoteProxy:publicPeerHolder,publicINTERFACE{
public:
explicitIRemoteProxy(constsptr&object);
~IRemoteProxy()override=default;
protected:
sptrAsObject()override;
};
template<typenameINTERFACE>
IRemoteProxy::IRemoteProxy(constsptr&object):PeerHolder(object)
{
}
template<typenameINTERFACE>sptrIRemoteProxy::AsObject()
{
returnRemote();
}
}//namespaceOHOS
IRemoteProxy 使用 c++ 的 crtp (奇特重現(xiàn)模板模式)編程,使得父類可以調(diào)用子類的方法。繼承自 peerhold (其實就是包括一個 IRemoteObject 對象)。
IRemoteStub:
namespaceOHOS{
template<typenameINTERFACE>classIRemoteStub:publicIPCObjectStub,publicINTERFACE{
public:
IRemoteStub();
virtual~IRemoteStub()=default;
sptrAsObject()override;
sptrAsInterface()override;
};
template<typenameINTERFACE>IRemoteStub::IRemoteStub():IPCObjectStub(INTERFACE::GetDescriptor()){}
template<typenameINTERFACE>sptrIRemoteStub::AsInterface()
{
returnthis;
}
template<typenameINTERFACE>sptrIRemoteStub::AsObject()
{
returnthis;
}
}//namespaceOHOS
stub 對象較于 proxy 對象復雜一些,也使用 crtp 編程。會繼承 IPCObjectStub(也是 iremoteObject 對象)。
看到這里,可能有人疑惑,為什么 proxy 調(diào)用,會直接調(diào)用到 stub 這端呢?
其實奧秘就在于 stub 繼承的 IPCObjectStub(繼承 iremoteObject)對象,就是這個 iremoteObject 對象。
proxy 的構(gòu)造繼承 peerhold,peerhold 類中的iremoteObject 對象和 IPCObjectStub 這個是什么關(guān)系呢?
其實 peerhold 是 IPCObjectStub 的引用對象,實際類型是 IPCObjectProxy。
這兩者在 ipc 框架中,IPCObjectProxy 實際使用 sendrequest,IPCObjectStub 便會調(diào)用 OnremoteRequest。如果有興趣,我們下次可以分析 IPC 框架具體是如何實現(xiàn)的。
原文標題:剖析鴻蒙經(jīng)典的proxy - stub架構(gòu)
文章出處:【微信公眾號:HarmonyOS技術(shù)社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
審核編輯:湯梓紅
-
內(nèi)核
+關(guān)注
關(guān)注
3文章
1416瀏覽量
41424 -
架構(gòu)
+關(guān)注
關(guān)注
1文章
528瀏覽量
25983 -
OpenHarmony
+關(guān)注
關(guān)注
29文章
3854瀏覽量
18604
原文標題:剖析鴻蒙經(jīng)典的proxy - stub架構(gòu)
文章出處:【微信號:gh_834c4b3d87fe,微信公眾號:OpenHarmony技術(shù)社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
評論