Hi3861的SAMGR--系統服務框架子系統-4-面向服務架構的實現
5. 面向服務架構的實現
SOA(service-oriented architectur,面向服務的架構是一種軟件架構或者軟件模型,這種架構下,系統提供的各種功能都會以服務的形式,提供給用戶或者系統內外的其它服務來使用,服務與服務之間是松耦合的關系,互相之間使用中立的接口和標準的方式進行通信和交互,與硬件平臺、操作系統、編程語言沒有相關性。這種架構特別適合在分布式的環境中使用,鴻蒙系統就是一個分布式的操作系統,自然采用了這種架構。【更多的SOA相關信息,請自行網上搜索學習。】
面向服務的架構,包括下面三種角色:
- Provider:服務的提供者,為系統提供能力(即對外接口),它接受和執行來自消費者的請求。
它將自己的服務和接口發布到服務管理中心,以便服務的消費者可以發現和訪問該服務。
- Consumer:服務的消費者,調用服務提供的功能(即對外接口)來實現某種結果。
它可以是一個應用程序、一個軟件模塊或者另一個服務,它發起對服務管理中心的服務查詢、綁定服務, 然后執行服務提供的能力。
- Samgr:服務管理中心是一個中介者,它管理著Provider提供的能力,同時幫助Consumer發現Provider的能力。
它們的關系如下圖所示:

前文《系統服務框架子系統-2》4.6 小節對PubSubFeature 和PubSubImplement結構體的分析,提到了它們是SOA(面向服務的架構)的實現,本節我們就來具體分析一下。
代碼結構為 Hi3861/distributedschedule/samgr_lite/communication/

我們還是先對PubSubFeature 和PubSubImplement結構體做比較完整的展開,如下圖:


兩個全局變量g_pubSubImplement和g_broadcastFeature也分別展開:
- g_pubSubImplement 的展開

如前文《系統服務框架子系統-2》“4.7 IUnknown 接口類及其相關定義” 所分析的,任何應用或者其他模塊通過:
- IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE, PUB_SUB_FEATURE);
就可以拿到上面的iUnknown的指針了,拿到這個指針后,就可以再通過:
- PubSubInterface *fapi = NULL;
- iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&fapi);
來恢復出PubSubInterface 對象的指針fapi,也就可以訪問 subscriber和provider的API了。
- g_broadcastFeature的展開

這里的重點是relations這個雙重的雙向鏈表及其node上所掛載的東西,注意,上圖的head node和tail node的指針會互相指向對方,形成閉環,這里沒有畫出來。
g_pubSubImplement 主要是提供一組統一的標準的對外的接口,外部程序可以通過這組接口來:
- 為Consumer訂閱(Subscribe) Topic
- 為Provider 發布(Publish) Topic
當某個Consumer[i]要訂閱某個Topic[x]的時候,首先需要通過AddTopic(Topic[x])將Topic[x]添加到relations鏈表中去,添加的時候會做檢查和判斷,確保Topic[x]不會在relations鏈表上重復添加。然后再通過Subscribe(Topic[x], Consumer[i])來訂閱Topic[x],實際上就是把Consumer[i]添加到Topic[x]的雙線鏈表中去,以獲得對Topic[x]的訂閱權限。
當某個Provider Publish一個Topic[x]的時候,Broadcast 的這個PubSubFeature會從relations鏈表中找到對應的Topic[x],對其所有訂閱者發起廣播(也就是遍歷Topic[x]的ConsumerNode鏈表,對鏈表上所有的consumer節點發送消息,讓它們對消息進行處理)。
簡單來說,g_pubSubImplement和g_broadcastFeature這兩個全局變量,g_broadcastFeatur提供了feature的生命周期和數據結構,g_pubSubImplemen則提供了對外接口和對數據結構的操作。具體他們是如何配合工作的,請自行閱讀broadcast目錄下的代碼。
附件包含兩個測試程序,分別是broadcast_example和user_button_test,以及它們跑起來的log,感興趣的朋友請自行編譯和做驗證。
- broadcast_example
以官方的samgr例程為樣本,框架是一樣的,跑的內容做了一些修改,按照我的習慣對log做了整理,基 本上相當于重寫了這個測試用例。
以CASE_AddAndUnsubscribeTopic()為例,我添加了4個Topic,三個Consumer對Topic的訂閱情況如下表:

當某個Topic[x] 發布的時候,只有訂閱了它的Consumer會做出反應,Consumer會調用callback函數對Topic[x]的request做出針對性的處理。
- user_button_test
我自己寫的Provider測試程序,Hi3861開發板響應user按鍵消息,每次按鍵事件觸發一次 Publish 一個隨機的 topic,以此檢驗上表中的Consumer對各自訂閱的Topic的處理情況。
按鍵線程 UserButtonTask 每1s循環一次,計數器++,檢測到按鍵按下時,當前計數器%5, 得到 0~4 的一個隨機數字,這個數字就是 topic,上表中只添加了topic[0~3],當UserButtonTask publish topic[4]時,就會出現異常,請查閱附件的log就知道是怎樣的了。
文章相關附件可以點擊下面的原文鏈接前往下載
原文鏈接:https://harmonyos.51cto.com/posts/4776