当前位置: 首页 > news >正文

openharmony5.0中HDF驱动框架源码梳理-服务管理接口

要想大概了解一个公司,我们可能只需要知道它的运行逻辑即可,例如我们只需要知道它有财务有研发有运营等,财务报销、研发负责产品等即可,但是如果想深入具体的了解的话我们就要了解都有什么部门(对象)、各部门都包含哪些职责(对象方法)以及各部门都包含哪些关键人员(子对象)以及他们的职责(子对象方法),根据这个逻辑我大概整理了openharmony 5.0的HDF框架中包含的关键对象以及对应的方法,便于更深的理解HDF的实现

一、源码目录

仓库路径仓库内容
drivers/hdf_core/frameworkHDF框架、平台驱动框架、驱动模型等平台无关化的公共框架。
- framework/core目录:驱动框架
  - 提供驱动框架能力,主要完成驱动加载和启动功能。
  - 通过对象管理器方式可实现驱动框架的弹性化部署和扩展。
- framework/model目录:驱动模型
  提供了模型化驱动能力,如网络设备模型。
- framework/ability目录:驱动能力库
  提供基础驱动能力模型,如IO通信能力模型。
- framework/tools目录:驱动工具
  提供HDI接口转换、驱动配置编译等工具。
- framework/support目录:Support
  提供规范化的平台驱动接口和系统接口抽象能力。
drivers/hdf_core/adapter包含所有LiteOS-M和LiteOS-A内核以及用户态接口库等相关适配代码以及编译脚本。
drivers/hdf_core/adapter/khdf/linux包含所有Linux内核相关适配代码以及编译脚本。
drivers/peripheralDisplay、Input、Sensor、WLAN、Audio、Camera等外设模块硬件抽象层。
drivers/interfaceDisplay、Input、Sensor、WLAN、Audio、Camera等外设模块HDI接口定义。

在这里插入图片描述

二、硬件驱动框架(HDF)

1. 驱动开发流程

驱动加载
驱动服务管理
驱动消息机制
配置管理
驱动模型
HDF驱动开发流程
按需加载,加载策略由配置文件中的preload字段来控制
preload为0:则系统启动过程中默认加载
preload为01:当系统支持快速启动的时候,则在系统完成之后再加载这一类驱动
preload为2:则系统启动过程中默认不加载,支持后续动态加载
按序加载(默认)
配置文件中的priority(整数0到200)是用来表示host(驱动容器)和驱动的优先级的
host和驱动都是priority值越小,加载优先级越高
驱动需要以接口的形式对外提供能力时使用
包含驱动服务的发布和获取
驱动对外发布服务的策略,由配置文件中的policy字段来控制
0:驱动不提供服务
1:驱动对内核态发布服务
2:驱动对内核态和用户态都发布服务
3:驱动服务不对外发布服务,但可以被订阅
4:驱动私有服务不对外发布服务,也不能被订阅
5:错误的服务策略
当用户态应用和内核态驱动需要交互时使用:
1.用户态应用发送消息到驱动
2.用户态应用接收驱动主动上报事件
HCS(HDF Configuration Source)是HDF驱动框架的配置描述源码。
它实现了配置代码与驱动代码解耦,便于开发者进行配置管理
HDF框架将一类设备驱动放在同一个Host(设备容器)里面,用于管理一组设备的启动加载等过程
划分Host时,驱动程序是部署在一个Host还是部署在不同的Host,主要考虑驱动程序之间是否存在耦合性

下面以驱动开发流程为主线,一步一步分析每个节点的代码实现,以求完全剖析实现逻辑。本篇为驱动服务管理部分
在看本篇前建议先看下openharmony中HDF驱动框架源码梳理-驱动加载流程这篇。

三、驱动服务管理说明

驱动服务是HDF驱动设备对外提供能力的对象,由HDF框架统一管理。驱动服务管理主要包含驱动服务的发布和获取。HDF框架定义了驱动对外发布服务的策略,由配置文件中的policy字段来控制,policy字段的取值范围以及含义如下:

typedef enum {
    /* 驱动不提供服务 */
    SERVICE_POLICY_NONE = 0,
    /* 驱动对内核态发布服务 */
    SERVICE_POLICY_PUBLIC = 1,
    /* 驱动对内核态和用户态都发布服务 */
    SERVICE_POLICY_CAPACITY = 2,
    /* 驱动服务不对外发布服务,但可以被订阅 */
    SERVICE_POLICY_FRIENDLY = 3,
    /* 驱动私有服务不对外发布服务,也不能被订阅 */
    SERVICE_POLICY_PRIVATE = 4,
    /* 错误的服务策略 */
    SERVICE_POLICY_INVALID
} ServicePolicy;

使用场景

当驱动需要以接口的形式对外提供能力时,可以使用HDF框架的驱动服务管理能力。

接口说明

针对驱动服务管理功能,HDF框架开放了以下接口供开发者调用,如下表所示:

表1 服务管理接口

方法描述
int32_t (*Bind)(struct HdfDeviceObject *deviceObject)需要驱动开发者实现Bind函数,将自己的服务接口绑定到HDF框架中。
const struct HdfObject *DevSvcManagerClntGetService(const char *svcName)获取驱动的服务。
int HdfDeviceSubscribeService( struct HdfDeviceObject *deviceObject, const char *serviceName, struct SubscriberCallback callback)订阅一个设备服务,在服务有更新时能够接收通知

获取驱动服务

通过服务名获取一个服务对象。

//drivers\hdf_core\interfaces\inner_api\host\shared\hdf_device_desc.h
//drivers\hdf_core\framework\core\host\src\devsvc_manager_clnt.c
const struct HdfObject *DevSvcManagerClntGetService(const char *svcName)
    |-->struct DevSvcManagerClnt *devSvcMgrClnt = DevSvcManagerClntGetInstance();//获取设备服务管理器客户端单实例
		|-->static struct DevSvcManagerClnt singletonInstance;
		|-->DevSvcManagerClntConstruct(&singletonInstance);
			|-->inst->devSvcMgrIf = (struct IDevSvcManager *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVSVC_MANAGER);//构造单实例对象,会调用DevSvcManagerExtCreate进行创建
	|-->serviceManager = devSvcMgrClnt->devSvcMgrIf;//将设备服务管理器客户端实例中的服务管理器接口赋值给 serviceManager
	|-->return serviceManager->GetService(serviceManager, svcName);//传入 serviceManager 和 svcName 作为参数,获取对应的服务对象
		|-->struct HdfObject *DevSvcManagerGetService(struct IDevSvcManager *inst, const char *svcName)//回调函数
            |-->uint32_t serviceKey = HdfStringMakeHashKey(svcName, 0);//根据服务名 svcName 和初始值 0 生成一个哈希键 serviceKey,用于快速查找服务记录
		   |-->serviceRecord = DevSvcManagerSearchServiceLocked(inst, serviceKey);//在服务管理器中查找指定哈希键 serviceKey 的服务记录,并将结果赋值给 serviceRecord
			   |-->DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {//遍历服务管理器中的服务记录链表 devSvcManager->services
            |-->deviceObject = serviceRecord->value;return deviceObject;//返回值

可参考类图如下:
在这里插入图片描述

由上图可知返回值为xxx,那么从哪里设置此值呢?可参考函数int DevSvcManagerAddService(struct IDevSvcManager *inst,struct HdfDeviceObject *service, const struct HdfServiceInfo *servInfo)驱动加载流程中有描述在这里插入图片描述

订阅一个设备服务,在服务有更新时能够接收通知

此函数允许一个观察者订阅一个特定的服务。如果服务已经存在,则直接将订阅者添加到该服务的订阅者列表中;如果服务不存在,则创建一个新的服务记录,并添加订阅者。如果服务已经发布,且订阅者的回调不为空,则立即调用OnServiceConnected回调。

//drivers\hdf_core\interfaces\inner_api\host\shared\hdf_device_desc.h
//drivers\hdf_core\framework\core\host\src\hdf_device_object.c
int32_t HdfDeviceSubscribeService(struct HdfDeviceObject *deviceObject, const char *serviceName, struct SubscriberCallback callback)
    |-->uint32_t serviceKey = HdfStringMakeHashKey(svcName, 0)//
    |-->serviceRecord = (struct HdfServiceObserverRecord *)HdfSListSearch(
        &observer->services, serviceKey, HdfServiceObserverRecordCompare);//在服务观察者的服务记录列表中查找指定哈希键 serviceKey 的服务记录
	|-->serviceRecord = HdfServiceObserverRecordObtain(serviceKey);//未找到服务时,创建新的服务记录 serviceRecord
	|-->subscriber = HdfServiceSubscriberObtain(callback, deviceId);//创建新的订阅者 subscriber
		|-->struct HdfServiceSubscriber *serviceSubscriber = (struct HdfServiceSubscriber *)OsalMemCalloc(sizeof(struct HdfServiceSubscriber)) //分配内存
         |-->serviceSubscriber->callback = callback//设置回调函数
	|-->subscriber->callback.OnServiceConnected(subscriber->callback.deviceObject, serviceRecord->publisher);//如果满足条件,设置订阅者的状态为 HDF_SUBSCRIBER_STATE_READY,并调用回调函数 OnServiceConnected
	|-->HdfSListAdd(&serviceRecord->subscribers, &subscriber->entry);//将订阅者添加到服务记录的订阅者列表中

可参考类图如下:
在这里插入图片描述

示例demo

以下是一个简单的示例,展示了如何在 OpenHarmony 的 HDF 框架中实现 Bind 函数、获取服务以及订阅服务:

示例代码

#include "hdf_device_desc.h"
#include "hdf_log.h"
#include "hdf_service_observer.h"

#define HDF_LOG_TAG sample_driver

// 定义驱动服务接口
struct ISampleDriverService {
    struct IDeviceIoService ioService;
    int32_t (*ServiceA)(void);
    int32_t (*ServiceB)(uint32_t inputCode);
};

// 实现驱动服务接口
int32_t SampleDriverServiceA(void) {
    HDF_LOGD("SampleDriverServiceA called");
    return HDF_SUCCESS;
}

int32_t SampleDriverServiceB(uint32_t inputCode) {
    HDF_LOGD("SampleDriverServiceB called with inputCode: %u", inputCode);
    return HDF_SUCCESS;
}

// 实现 Bind 函数
int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) {
    if (deviceObject == NULL) {
        HDF_LOGE("deviceObject is null");
        return HDF_FAILURE;
    }
    static struct ISampleDriverService sampleDriverService = {
        .ServiceA = SampleDriverServiceA,
        .ServiceB = SampleDriverServiceB,
    };
    deviceObject->service = &sampleDriverService.ioService;
    HDF_LOGD("Sample driver bind success");
    return HDF_SUCCESS;
}

// 实现 Init 函数
int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) {
    HDF_LOGD("Sample driver init success");
    return HDF_SUCCESS;
}

// 实现 Release 函数
void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) {
    HDF_LOGD("Sample driver release success");
}

// 定义驱动入口
struct HdfDriverEntry g_sampleDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "sample_driver",
    .Bind = HdfSampleDriverBind,
    .Init = HdfSampleDriverInit,
    .Release = HdfSampleDriverRelease,
};

// 注册驱动入口
HDF_INIT(g_sampleDriverEntry);

// 获取服务示例
const struct HdfObject *GetSampleDriverService(const char *svcName) {
    return DevSvcManagerClntGetService(svcName);
}

// 订阅服务回调函数
int32_t SampleDriverSubCallBack(struct HdfDeviceObject *deviceObject, const struct HdfObject *service) {
    const struct ISampleDriverService *sampleService = (const struct ISampleDriverService *)service;
    if (sampleService != NULL) {
        sampleService->ServiceA();
        sampleService->ServiceB(5);
    }
    return HDF_SUCCESS;
}

// 订阅服务示例
int32_t SubscribeSampleDriverService(struct HdfDeviceObject *deviceObject, const char *serviceName) {
    struct SubscriberCallback callback = {
        .deviceObject = deviceObject,
        .OnServiceConnected = SampleDriverSubCallBack,
    };
    return HdfDeviceSubscribeService(deviceObject, serviceName, callback);
}

说明

  1. Bind 函数实现

    • HdfSampleDriverBind 函数中,将驱动的服务接口 sampleDriverService 绑定到 HDF 框架中。
    • deviceObject->service 设置为服务接口的指针。
  2. 获取服务

    • 使用 DevSvcManagerClntGetService 函数通过服务名获取驱动的服务对象。
  3. 订阅服务

    • 定义回调函数 SampleDriverSubCallBack,在服务连接时调用。
    • 使用 HdfDeviceSubscribeService 函数订阅指定的服务,在服务加载完成后,HDF 框架会调用回调函数。

使用方法

  • 在驱动的配置文件中,指定服务的发布策略(如 SERVICE_POLICY_PUBLIC)。
  • 在驱动的初始化函数中,调用 SubscribeSampleDriverService 函数订阅所需的服务。

这个示例展示了如何在 OpenHarmony 的 HDF 框架中实现驱动服务的绑定、获取和订阅功能,帮助开发者更好地理解和使用这些机制。

相关文章:

  • Deny by project hooks setting ‘default‘: size of the file
  • Android自动化测试工具
  • tcpdump剖析:入门网络流量分析实战指南
  • 《Operating System Concepts》阅读笔记:p286-p308
  • 关于使用Visual Studio编码问题
  • 30天学习Java第四天——设计模式
  • RabbitMQ之旅(2)
  • Python----数据可视化(Pyecharts三:绘图二:涟漪散点图,K线图,漏斗图,雷达图,词云图,地图,柱状图折线图组合,时间线轮廓图)
  • 阿里云魔笔低代码应用开发平台快速搭建教程
  • 【C++】string类的相关成员函数以及string的模拟实现
  • leecode200.岛屿数量
  • Nginx快速上手
  • 【AI与大模型】解锁本地大模型的潜力:Ollama API 调用深度解析与实践指南
  • springboot常用注解
  • YOLOv11来了,使用YOLOv11训练自己的数据集和推理(附YOLOv11网络结构图)
  • WinForm基础知识1-20
  • dockerfile 编写入门
  • DeepSeek linux服务器(CentOS)部署命令笔记
  • Linux date 命令使用指南
  • 利用亚马逊云科技”多模态AI知识库“获取非结构化数据总结
  • 国家卫健委通报:吊销肖某医师执业证书,撤销董某莹四项证书
  • Offer触手可及,2025上海社会组织联合招聘专场活动正寻找发光的你
  • 鸿海下调全年营收展望:AI服务器业务强劲,预计今年营收增超50%
  • 秘鲁总理辞职
  • 男子入户强奸高龄独居妇女致其死亡,法院:属实,已执行死刑
  • 外交部:反对美方人士发表不负责任谬论