0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

HDI的IPC模式具體實現(xiàn)方法和驅(qū)動框架能力

HarmonyOS開發(fā)者 ? 來源:OpenAtom OpenHarmony ? 作者:OAOH ? 2021-09-08 11:26 ? 次閱讀

轉(zhuǎn)自:OpenAtom OpenHarmony

HDI接口概述

HDF 驅(qū)動框架的一個重要功能是為系統(tǒng)提供穩(wěn)定的統(tǒng)一的硬件接口,這樣才能保證系統(tǒng)服務可以運行在不同硬件上而不需要額外的適配工作,而HDI(Hardware Device Interfaces)正是為了實現(xiàn)該目的而設計。

HDI 是對硬件功能的較高層次抽象接口,各類外設完成 HDI 接口定義后便只會在 HDI 的兼容性規(guī)則下進行變更,從而保證接口的穩(wěn)定性。具體的驅(qū)動實現(xiàn)不需要再重復定義 HDI 接口,只需要按需實現(xiàn)即可接入系統(tǒng)功能。

在不同量級的 OpenHarmony 系統(tǒng)上,HDI 存在兩種部署形態(tài),IPC 模式和直通模式。

6c08c6dc-1053-11ec-8fb8-12bb97331649.png

在輕量級 OpenHarmony 系統(tǒng)上,出于減小系統(tǒng)性能負載考慮,HDI 實現(xiàn)為用戶態(tài)共享庫,由系統(tǒng)服務直接加載 HDI 實現(xiàn)到自己進程中函數(shù)調(diào)用使用。HDI 實現(xiàn)封裝具體的用戶態(tài)-內(nèi)核態(tài)交互過程,當需要訪問驅(qū)動程序時使用 IO Service 請求將消息通過 system call 方式調(diào)用到內(nèi)核驅(qū)動實現(xiàn)。

在 OpenHarmony 系統(tǒng)上,HDI 以獨立服務進程方式部署,系統(tǒng)服務只加載 HDI 客戶端實現(xiàn)到自己進程中,實際業(yè)務運行在獨立進程中,客戶端通過 IPC 與服務端交互,便于架構解耦、權限管理。

HDI接口實現(xiàn)

直通模式為函數(shù)實現(xiàn)方式,無論調(diào)用還是實現(xiàn)都不需要其他組件支持即可實現(xiàn),這里將重點分析 IPC 模式的實現(xiàn)。

HDI發(fā)布

6c18f5a2-1053-11ec-8fb8-12bb97331649.png

HDI IPC 模式基于 OpenHarmony 系統(tǒng)通信框架的通用模型,但是因為驅(qū)動很多時候涉及到底層操作和多系統(tǒng)遷移的場景而使用C語言編寫,所以驅(qū)動框架還提供了 HDI 服務的 C 語言實現(xiàn)的基礎組件,C++實現(xiàn)則主要使用系統(tǒng)通信框架組件。

HDI 服務發(fā)布基于 UHDF(用戶態(tài) HDF 驅(qū)動框架)實現(xiàn),通用的服務發(fā)布實現(xiàn)如下。

1.實現(xiàn)驅(qū)動入口

int SampleDriverBind(struct HdfDeviceObject *deviceObject){ HDF_LOGE(“SampleDriverBind enter!”); static struct IDeviceIoService testService = { .Dispatch = SampleServiceDispatch, // 服務回調(diào)接口 }; deviceObject-》service = &testService; return HDF_SUCCESS;} int SampleDriverInit(struct HdfDeviceObject *deviceObject){ HDF_LOGE(“SampleDriverInit enter”); return HDF_SUCCESS;} void SampleDriverRelease(struct HdfDeviceObject *deviceObject){ HDF_LOGE(“SampleDriverRelease enter”); return;} struct HdfDriverEntry g_sampleDriverEntry = { .moduleVersion = 1, .moduleName = “sample_driver”, .Bind = SampleDriverBind, .Init = SampleDriverInit, .Release = SampleDriverRelease,};

HDF_INIT(g_sampleDriverEntry);

首先要添加一個 UHDF 驅(qū)動用于發(fā)布 IoService 服務,IoService 設備服務即為 HDI 服務實體。實現(xiàn)方式與 KHDF 驅(qū)動一致。

2.實現(xiàn)服務響應接口

int32_t SampleServiceOnRemoteRequest(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply){ switch (cmdId) { case SAMPLE_SERVICE_PING: return SampleServiceStubPing(client, data, reply); … … default: HDF_LOGE(“SampleServiceDispatch: not support cmd %d”, cmdId); return HDF_ERR_INVALID_PARAM; }}static int32_t SampleServiceDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply){ return SampleServiceOnRemoteRequest(client, cmdId, data, reply);}

當收到 HDI 調(diào)用時,服務響應接口“SampleServiceDispatch”將會被調(diào)用。

client 調(diào)用者對象,在用戶態(tài)驅(qū)動中暫時未支持

cmdId 調(diào)用命令字,用于區(qū)分調(diào)用的 API

data 調(diào)用入?yún)⑿蛄谢瘜ο?,?IPC 調(diào)用場景為 parcel 對象的 C 語言封裝,入?yún)⑿枰褂眯蛄谢涌趶?data 對象中獲取后再使用

reply 調(diào)用出參對象,需要返回給調(diào)用的信息寫入該序列化對象

如果 C++實現(xiàn)客戶端可以使用下面接口將 sbuf 對象轉(zhuǎn)換為 parcel 對象后操作:

int32_t SbufToParcel(struct HdfSBuf *sbuf, OHOS::MessageParcel **parcel);

3.UHDF 驅(qū)動配置

platform :: host { hostName = “sample_host”; priority = 50; sample_device :: device { device0 :: deviceNode { policy = 2; priority = 100; moduleName = “l(fā)ibsample_driver.z.so”; serviceName = “sample_driver_service”; } }}

參數(shù)說明:

host 一個 host 節(jié)點即為一個獨立進程,如果需要獨立進程,新增屬于自己的 host 節(jié)點

policy 服務發(fā)布策略,HDI 服務設置為 2

moduleName 驅(qū)動實現(xiàn)庫名

serviceName 服務名稱,請保持全局唯一性

因為 HDI 服務 C 和 C++實現(xiàn)使用的 IPC 組件不一樣,面向?qū)ο髮崿F(xiàn)也不一致,所以在具體實現(xiàn)上存在一些差異。

HDI基礎組件UHDF 框架為了支持 HDI 實現(xiàn),提供了以下基礎組件(僅用于 C 語言 HDI 實現(xiàn)):

SBuf

SBuf 是同時支持 KHDF 和 UHDF 驅(qū)動 IoService 消息序列化的工具對象。在 UHDF IPC 通信場景中,SBuf 可以與系統(tǒng) IPC 框架序列化對象 MessageParcel 對象(僅支持 C++)相互轉(zhuǎn)換,從而實現(xiàn) C 和 C++實現(xiàn)的 IPC 互通。

常用 API 如下:

struct HdfSBuf;struct HdfSbufImpl;struct HdfRemoteService;

/** * @brief HdfSBuf類型定義。 * * @since 1.0 */enum HdfSbufType { SBUF_RAW = 0, /* 用于用戶態(tài)內(nèi)核態(tài)通信的sbuf類型 */ SBUF_IPC, /* 用于跨進程通信的sbuf類型 */ SBUF_IPC_HW, /* 用于擴展的預留類型 */ SBUF_TYPE_MAX, /* sbuf類型最大值 */};

6c5c0aea-1053-11ec-8fb8-12bb97331649.png

上述接口均有對應的寫入接口,不再一一列舉,可查閱官網(wǎng)API參考文檔。

RemoteService

RemoteService 對象和系統(tǒng) IPC 框架中的 IRemoteObject 對象(僅支持 C++)對應并可以相互轉(zhuǎn)換,表示一個 IPC 對象。相關 API 說明:

// 消息分發(fā)器,用于服務端響應調(diào)用或者在客戶端發(fā)起調(diào)用struct HdfRemoteDispatcher { int (*Dispatch)(struct HdfRemoteService *, int, struct HdfSBuf *, struct HdfSBuf *);};

// RemoteService 死亡回調(diào)對象struct HdfDeathRecipient { void (*OnRemoteDied)(struct HdfDeathRecipient *, struct HdfRemoteService *);};

struct HdfRemoteService { struct HdfObject object_; struct HdfObject *target; struct HdfRemoteDispatcher *dispatcher; bool isHw;};// 以自定義的消息分發(fā)器實例化一個RemoteServicestruct HdfRemoteService *HdfRemoteServiceObtain( struct HdfObject *object, struct HdfRemoteDispatcher *dispatcher);

// 回收RemoteService對象void HdfRemoteServiceRecycle(struct HdfRemoteService *service);

// 添加RemoteService的死亡通知,如果對應RemoteService的進程異常退出,HdfDeathRecipient的回調(diào)接口將被調(diào)用void HdfRemoteServiceAddDeathRecipient(struct HdfRemoteService *service, struct HdfDeathRecipient *recipient);

基于 RemoteService 實現(xiàn)一個服務端的示例:

int SampleServiceStubDispatch( struct HdfRemoteService* service, int code, struct HdfSBuf *data, struct HdfSBuf *reply){ // IPC 調(diào)用響應接口 int ret = HDF_FAILURE; switch (code) { case SAMPLE_IF_0: { // do something break; } default: { ret = HDF_ERR_INVALID_PARAM; } } return ret;}bool SampleStubConstruct(){ // 構造消息分發(fā)器,實現(xiàn)消息處理回調(diào) static struct HdfRemoteDispatcher dispatcher = { .Dispatch = SampleServiceStubDispatch};// 實例化RemoteService inst-》remote = HdfRemoteServiceObtain((struct HdfObject *)inst, &dispatcher); if (inst-》remote == NULL) { HDF_LOGE(“Device service manager failed to obtain remote service”); return false;}… …

直接基于 RemoteService 實現(xiàn)服務端只適用于需要實現(xiàn)匿名 IPC 服務的情況,基于 UHDF 發(fā)布 HDI 服務只需要實現(xiàn) Driver 綁定的 IoService 即可。

RemoteService 客戶端對象只能從 SBuf HdfSBufReadRemoteService 接口獲取。

HDI實現(xiàn)

6c7588e4-1053-11ec-8fb8-12bb97331649.png

Driver 為 HDI 服務的驅(qū)動入口實現(xiàn)

IoService 為 HDI 服務的服務入口實現(xiàn),IoService 的 Dispatch 方法中調(diào)用 ServiceStub 中的真正服務響應接口(OnRemoteRequest)

ServiceStub 為服務端實現(xiàn)對象,主要處理與 IPC 相關的業(yè)務邏輯,在這里完成參數(shù)反序列化后調(diào)用真正的 Service 實現(xiàn)接口,即 ServiceImpl 接口

ServiceImpl 為 HDI 接口的真正實現(xiàn),這里不關注 IPC 過程,只實現(xiàn)函數(shù)接口。

驅(qū)動框架提供了實現(xiàn)的樣例代碼,可參考 gitee driver 代碼倉。

HDI接口調(diào)用

HDI驅(qū)動框架HDI接口

HDI 服務管理功能由驅(qū)動框架 DeviceManager 實現(xiàn),所以驅(qū)動框架提供了 HDI 服務管理相關 HDI 接口。

C++實現(xiàn):

namespace OHOS {namespace HDI {namespace ServiceManager {namespace V1_0 {

struct IServiceManager : public IRemoteBroker {public: DECLARE_INTERFACE_DESCRIPTOR(u“HDI.IServiceManager.V1_0”); // get()靜態(tài)方法用于獲取IServiceManager對象實例 static ::sptr《IServiceManager》 Get(); // GetService()接口是真正提供的HDI接口,用于查詢并獲取其他HDI服務的客戶端對象 virtual ::sptr《IRemoteObject》 GetService(const char* serviceName) = 0;};} // namespace V1_0} // namespace ServiceManager} // namespace HDI} // namespace OHOS

C 實現(xiàn):

#ifdef __cplusplusextern “C” {#endif /* __cplusplus */

struct HDIServiceManager { struct HdfRemoteService *remote;

struct HdfRemoteService *(*GetService)(struct HDIServiceManager *self, const char* serviceName);};

struct HDIServiceManager *HDIServiceManagerGet(void);void HDIServiceManagerRelease(struct HDIServiceManager *servmgr);

#ifdef __cplusplus}#endif /* __cplusplus */

C 語言因為缺少原生的面向?qū)ο笾С?,這里我們采用 OOC 的實現(xiàn),函數(shù)方法 HDIServiceManagerGet/Release 用于 HDIServiceManager 對象的實例化和釋放,HDI 接口關聯(lián)在接口對象內(nèi)部成員中,與 C++實現(xiàn)類似。

HDI客戶端實現(xiàn)

HDI 客戶端同時支持 C 和 C++實現(xiàn),實現(xiàn)方法較為簡單,只需 realize HDI 接口類即可。提供 C++實現(xiàn)基于系統(tǒng) IPC 子系統(tǒng)的統(tǒng)一模型,C 語言基于 RemoteService 和 SBuf 組件實現(xiàn),但是有一些公共的約定:

1.客戶端提供接口對象,接口與對象綁定且必須與 HDI 一致

2.提供服務接口對象的實例化和釋放接口。

3.客戶端實現(xiàn) IPC 過程,只為調(diào)用者暴露函數(shù)化接口。

HDI接口調(diào)用

HDI 客戶端接口已經(jīng)提供了服務獲取接口,調(diào)用者調(diào)用服務獲取接口后再調(diào)用服務對象方法即可完成 HDI 調(diào)用。

這里以服務管理 HDI 接口為例:

C++接口調(diào)用:

#include 《iservmgr_hdi.h》

void GetTestService(){ auto servmgr = IServiceManager::Get(); if (servmgr == nullptr) { HDF_LOGE(“failed to get IServiceManager”); return; }

auto sampleService = servmgr-》GetService(TEST_SERVICE_NAME); if (sampleService == nullptr) { HDF_LOGE(“failed to get TEST_SERVICE”); return; } // do something}

C 接口調(diào)用:

#include 《servmgr_hdi.h》

void GetTestService(){ struct HDIServiceManager *servmgr = HDIServiceManagerGet(); if (servmgr == nullptr) { HDF_LOGE(“failed to get IServiceManager”); return; }

struct HdfRemoteService *sampleService = servmgr-》GetService(servmgr, TEST_SERVICE_NAME); if (sampleService == nullptr) { HDF_LOGE(“failed to get TEST_SERVICE”); return; } // do something}

總結

本文介紹了 HDI 的總體方案,重點介紹了 HDI 的 IPC 模式具體實現(xiàn)方法和驅(qū)動框架能力,相信對讀者理解和使用 HDI 有所幫助。

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • API
    API
    +關注

    關注

    2

    文章

    1468

    瀏覽量

    61694
  • HDI
    HDI
    +關注

    關注

    6

    文章

    188

    瀏覽量

    21255
  • IPC
    IPC
    +關注

    關注

    3

    文章

    336

    瀏覽量

    51725
  • OpenHarmony
    +關注

    關注

    25

    文章

    3614

    瀏覽量

    15990
收藏 人收藏

    評論

    相關推薦

    如何判斷盲/埋孔HDI板有多少“階”?

    激光鉆孔 ,具體取決于設計需求和制造能力。 盲/埋孔HDI板有很多種結構,行業(yè)內(nèi)是用階數(shù)來區(qū)分的。簡單理解“階”就是臺階,上一步臺階為一階,上兩步臺階為二階。那么盲/埋孔HDI板理解
    發(fā)表于 10-23 18:38

    Scrum框架模式、過程和見解

    電子發(fā)燒友網(wǎng)站提供《Scrum框架模式、過程和見解.pdf》資料免費下載
    發(fā)表于 08-12 09:36 ?0次下載

    什么是HDI?PCB設計基礎與HDI PCB制造工藝

    隨著科技的發(fā)展,將更多功能集成在更小的封裝中的需求也隨之增長。使用高密度互連(HDI)技術設計的PCB通常更小,因為更多的元件被裝在更小的空間里。HDIPCB使用盲孔、埋孔和微孔、焊盤內(nèi)孔以及非常細
    的頭像 發(fā)表于 07-22 18:21 ?3161次閱讀
    什么是<b class='flag-5'>HDI</b>?PCB設計基礎與<b class='flag-5'>HDI</b> PCB制造工藝

    松下伺服驅(qū)動器速度模式參數(shù)設置方法

    詳細介紹松下伺服驅(qū)動器速度模式參數(shù)設置方法。 一、速度模式概述 速度模式是伺服驅(qū)動器的一種基本控
    的頭像 發(fā)表于 06-12 10:25 ?3251次閱讀

    鴻蒙OS跨進程IPC與RPC通信

    ) = 0; // 定義業(yè)務函數(shù) }; 3.定義和實現(xiàn)服務端TestAbilityStub 該類是和IPC框架相關的實現(xiàn),需要繼承 IRemoteStub。Stub端作為接收請求的一
    發(fā)表于 02-17 14:20

    HarmonyOS跨進程通信—IPC與RPC通信開發(fā)

    一、IPC與RPC通信概述 基本概念 IPC(Inter-Process Communication)與RPC(Remote Procedure Call)用于實現(xiàn)跨進程通信,不同的是前者
    的頭像 發(fā)表于 02-02 17:47 ?1170次閱讀
    HarmonyOS跨進程通信—<b class='flag-5'>IPC</b>與RPC通信開發(fā)

    IPC-TM-650-CN測試方法手冊

    電子發(fā)燒友網(wǎng)站提供《IPC-TM-650-CN測試方法手冊.pdf》資料免費下載
    發(fā)表于 12-25 09:38 ?75次下載

    IPC-660

    IPC
    GITSTAR 集特工控
    發(fā)布于 :2023年12月20日 14:53:06

    HDI 布線的挑戰(zhàn)和技巧

    HDI 布線的挑戰(zhàn)和技巧
    的頭像 發(fā)表于 12-07 14:48 ?463次閱讀

    0-10v輸出電路驅(qū)動能力的計算方法

    在電子系統(tǒng)中,輸出電路驅(qū)動能力是指電路輸出端可以提供的電流或功率。在0-10V輸出電路中,驅(qū)動能力首先取決于能夠輸出的最大電流和最大功率。本文將詳細介紹0-10V輸出電路驅(qū)動能力的相關概念、計算
    的頭像 發(fā)表于 12-07 14:45 ?1792次閱讀

    什么是HDI板?HDI板中的一階,二階是怎么定義的?

    什么是HDI板?HDI板中的一階,二階是怎么定義的? HDI(High-Density Interconnect)是一種高密度互連技術,用于在電子設備中實現(xiàn)更多的線路和連接點。它利用微
    的頭像 發(fā)表于 12-07 09:59 ?4199次閱讀

    高密度互連印刷電路板:如何實現(xiàn)高密度互連 HDI

    高密度互連印刷電路板:如何實現(xiàn)高密度互連 HDI
    的頭像 發(fā)表于 12-05 16:42 ?658次閱讀
    高密度互連印刷電路板:如何<b class='flag-5'>實現(xiàn)</b>高密度互連 <b class='flag-5'>HDI</b>

    如何管理高密 HDI 過孔

    如何管理高密 HDI 過孔
    的頭像 發(fā)表于 12-05 16:32 ?417次閱讀
    如何管理高密 <b class='flag-5'>HDI</b> 過孔

    力控機器人控制方法框架及其性能分析

    交互控制框架是用于實現(xiàn)機器人與外部環(huán)境或操作者之間的力互動的控制系統(tǒng)。 在力控機器人交互控制中,主要涉及直接力控制、阻抗控制和導納控制三種主要方法。下面是這些控制方法
    的頭像 發(fā)表于 11-09 15:59 ?1082次閱讀
    力控機器人控制<b class='flag-5'>方法</b>的<b class='flag-5'>框架</b>及其性能分析

    基于表驅(qū)動的健康監(jiān)控機制實現(xiàn)方法

    電子發(fā)燒友網(wǎng)站提供《基于表驅(qū)動的健康監(jiān)控機制實現(xiàn)方法.pdf》資料免費下載
    發(fā)表于 11-06 10:09 ?0次下載
    基于表<b class='flag-5'>驅(qū)動</b>的健康監(jiān)控機制<b class='flag-5'>實現(xiàn)</b><b class='flag-5'>方法</b>