幼儿园东莞网站建设/成都最新热门事件

幼儿园东莞网站建设,成都最新热门事件,注册咨询服务公司有什么要求,怎样申请网络域名openharmony中hdf框架的驱动消息机制的实现原理 在分析hdf框架时发现绕来绕去的,整体梳理画了一遍流程图,发现还是有点模糊甚至不清楚如何使用的,详细的每个点都去剖析细节又过于消耗时间,所以有时间便从功能应用的角度一块块的去…

openharmony中hdf框架的驱动消息机制的实现原理

在分析hdf框架时发现绕来绕去的,整体梳理画了一遍流程图,发现还是有点模糊甚至不清楚如何使用的,详细的每个点都去剖析细节又过于消耗时间,所以有时间便从功能应用的角度一块块的去梳理。

此文为参考官方源码(oh5.0版本)中的docs\zh-cn\device-dev\driver\driver-hdf-manage.md驱动开发手册,将驱动消息机制这个小章节拿出来,单独做剖析的。官方手册中只涉及了如何使用,未涉及具体的原理。本文会先整体说下实现原理,然后结合驱动开发手册将涉及使用hdf接口函数的部分再往下剖了一下,目的是了解具体的实现逻辑。

概述

HDF框架提供统一的驱动消息机制,支持用户态应用向内核态驱动发送消息,也支持内核态驱动向用户态应用发送消息,用于当用户态应用和内核态驱动需要交互的场景。

使用分析

由原理可知消息机制的功能主要有以下两种:

  • 用户态应用发送消息到驱动。
  • 用户态应用接收驱动主动上报事件。

表2 消息机制接口

方法描述
struct HdfIoService *HdfIoServiceBind(const char *serviceName);用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。
void HdfIoServiceRecycle(struct HdfIoService *service);用户态释放驱动的服务,与HdfIoServiceBind对应
int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);用户态程序注册接收驱动上报事件的操作方法。
int32_t HdfDeviceSendEvent(const struct HdfDeviceObject *deviceObject, uint32_t id, const struct HdfSBuf *data)驱动主动上报事件接口。当驱动服务调用此函数发送消息时,所有通过 HdfDeviceRegisterEventListener注册了监听器的用户级应用程序都将收到该消息。

HdfIoServiceBind

用户态获取驱动的服务获取该服务之后通过服务中的Dispatch方法向驱动发送消息(见示例),函数的声明在接口文件中hdf_core\interfaces\inner_api\core\hdf_io_service_if.h,驱动开发者可以直接包含调用。

struct HdfIoService *HdfIoServiceBind(const char *serviceName)|-->HdfIoServiceAdapterObtain(serviceName) //获取设备服务接口的适配器函数|-->svcMgr = DevSvcManagerClntGetInstance();//获取设备服务管理实例|-->HdfDeviceObject *deviceObject = svcMgr->devSvcMgrIf->GetObject(svcMgr->devSvcMgrIf, serviceName);//通过设备服务管理器获取设备对象|-->DevSvcManagerGetObject //通过获取设备服务管理实例的创建过程可知上述函数的回调为此函数|-->serviceRecord = DevSvcManagerSearchServiceLocked(inst, serviceKey)//从设备服务管理器中搜索该名称的服务|-->return serviceRecord->value //返回设备对象|-->HdfIoServiceKClient *kClient = HdfHdfIoServiceKClientInstance(deviceObject)//通过设备对象获取设备服务的客户端实例|-->kDispatcher = {.Dispatch = HdfKIoServiceDispatch,};|-->struct HdfIoServiceKClient *client = OsalMemCalloc(sizeof(struct HdfIoServiceKClient))//分配内存|-->if (deviceObject->service->Open(&client->client) != HDF_SUCCESS)//回调驱动层的open函数|-->client->ioService.dispatcher = &kDispatcher//绑定具体的接口,|-->return &kClient->ioService//返回设备服务接口

HdfIoServiceRecycle

用户态释放驱动的服务,与HdfIoServiceBind对应,声明在接口文件中hdf_core\interfaces\inner_api\core\hdf_io_service_if.h,驱动开发者可以直接包含调用。

void HdfIoServiceRecycle(struct HdfIoService *service)|-->HdfIoServiceAdapterRecycle(service)|-->HdfIoServiceKClient *kClient = CONTAINER_OF(ioService, struct HdfIoServiceKClient, ioService)//根据ioService反推HdfIoServiceKClient对象①|-->kClient->client.device->service->Release(&kClient->client)//客户端设备的释放②|-->OsalMemFree(kClient)//对应HdfIoServiceBind函数中的HdfHdfIoServiceKClientInstance

①:关于反推函数CONTAINER_OF需要详细的了解的可以参考这篇文章

②:客户端设备的释放是在设备构建过程中构建的io服务的设备接口(IDeviceIoService),从整体的流程图中方便看,但太大了没法放上来,后续有时间整理了这部分再重新放上链接。✒️

HdfDeviceRegisterEventListener

用户态程序注册接收驱动上报事件的操作方法

int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener)|-->return HdfDeviceRegisterEventListenerWithSchedPolicy(target, listener, SCHED_OTHER)//为设备服务注册事件监听器,并指定事件处理线程的调度策略|-->struct HdfSyscallAdapter *adapter = CONTAINER_OF(target, struct HdfSyscallAdapter, super)//从HdfIoService结构体中获取其所属的HdfSyscallAdapter实例|-->if (!AddListenerToAdapterLocked(adapter, listener)) //将事件监听器添加到适配器中|--> ret = HdfIoServiceGroupThreadStart(adapter->group, policy) //如果适配器属于一个服务组(adapter->group不为空)便启动服务组的线程,并指定调度策略(policy即传入的SCHED_OTHER)|--> if (HdfIoServiceGroupThreadInit(group) != HDF_SUCCESS) //对线程的初始化|-->HdfDevListenerThreadDoInit(thread) |-->int32_t ret = OsalThreadCreate(&thread->thread, HdfDevEventListenTask, thread)//创建监听线程|-->//....路径较多省略了|-->int32_t HdfDevEventDispatchLocked(const struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter, const struct HdfWriteReadBuf *bwr)|-->(void)listener->callBack(listener->priv, bwr->cmdCode, sbuf)//此处进行监听事件的回调①|--> int32_t ret = HdfDevListenerThreadStart(group->thread)//初始化设备监听线程,并启动一个线程来处理设备事件|-->int32_t ret = HdfListenThreadInitPollFds(thread)//初始化监听的文件描述符列表|-->if (HdfAdapterStartListenIoctl(thread->pfds[i].fd)) {//启动监听|-->if (OsalThreadStart(&thread->thread, &config) != HDF_SUCCESS) {//启动线程return ret;|-->if (HdfIoServiceStartListen(adapter, policy) != HDF_SUCCESS)//如果适配器不属于服务组,启动事件处理线程,并指定调度策略|-->return HdfDevListenerThreadStart(adapter->thread)//初始化设备监听线程,并启动一个线程来处理设备事件
  • SCHED_OTHER是linux系统中默认的进程调度策略,想详细了解进程调度策略可以参考这篇文章

  • 在本文后续的使用示例中可见此函数的使用的目的,主要是为了将事件进行回调,其中回调部分可参看本段代码的①处。

static struct HdfDevEventlistener listener = {.callBack = OnDevEventReceived,.priv ="Service0"
};
if (HdfDeviceRegisterEventListener(serv, &listener) != 0) {HDF_LOGE("fail to register event listener");return HDF_FAILURE;
}
  • 在此段代码中还可见有文件描述符的处理,即应用中我们用的selectpollepoll等。

HdfDeviceSendEvent

驱动主动上报事件接口,驱动服务调用此函数发送消息时,所有通过 HdfDeviceRegisterEventListener注册了监听器的用户级应用程序都将收到该消息。声明的头文件在hdf_core\interfaces\inner_api\host\shared\hdf_device_desc.h,意味着用户态可以直接包含调用。

int32_t HdfDeviceSendEvent(const struct HdfDeviceObject *deviceObject, uint32_t id, const struct HdfSBuf *data)|-->struct HdfDeviceNode *deviceNode = CONTAINER_OF(deviceObject, struct HdfDeviceNode, deviceObject)|-->adapter = (struct HdfVNodeAdapter *)(((struct DeviceNodeExt *)deviceNode)->ioService)|-->return HdfVNodeAdapterSendDevEvent(adapter, NULL, id, data)|-->ret = VNodeAdapterSendDevEventToClient(client, id, data)//将设备事件从驱动程序发送到客户端(通常是用户态应用程序或服务)|-->event = OsalMemAlloc(sizeof(struct HdfDevEvent));//分配事件对象|--> event->data = HdfSbufCopy(data);//给事件对象赋值|-->DListInsertTail(&event->listNode, &vnodeClient->eventQueue) //将事件对象插入到客户端的事件队列|-->wake_up_interruptible(&vnodeClient->pollWait)//唤醒等待事件的客户端线程
  • 唤醒等待事件的客户端线程的wake_up_interruptible函数为linux内核的api函数,有需要详细了解的可以直接百度,想了解简单使用方法的可以参考这篇文章。

使用示例

驱动消息机制管理开发

  1. 将驱动配置信息(device_info.hcs)中服务策略policy字段设置为2(SERVICE_POLICY_CAPACITY,驱动对内核态和用户态都发布服务)。

    device_sample :: Device {policy = 2;permission = 0644;...
    }
    
  2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。

    权限值含义
    0666所有用户都可以读写该设备节点
    0644所有者可以读写,所属组和其他用户可以读取
    0640所有者可以读写,所属组可以读取,其他用户无法访问
    0600只有所有者可以读写,其他用户无法访问
  3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法

    #include <hdf_log.h>
    #include <hdf_device_io.h>
    #include <hdf_device_desc.h>
    #include <hdf_sbuf.h>// 假设的其他服务函数
    int32_t SampleDriverServiceA(struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply) {HDF_LOGI("SampleDriverServiceA called");return HDF_SUCCESS;
    }int32_t SampleDriverServiceB(struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply) {HDF_LOGI("SampleDriverServiceB called");return HDF_SUCCESS;
    }// I/O 请求处理函数
    int32_t SampleDriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) {HDF_LOGI("SampleDriverDispatch called with cmdCode: %d", cmdCode);// 根据 cmdCode 处理不同的命令switch (cmdCode) {case 1:HDF_LOGI("Handling command 1");// 处理命令 1 的逻辑const char *msg = "Hello from driver";struct HdfSBuf *eventData = HdfSbufObtainDefaultSize();  // 创建事件数据缓冲区if (eventData == NULL) {HDF_LOGE("fail to obtain sbuf for event data");return HDF_DEV_ERR_NO_MEMORY;}if (!HdfSbufWriteString(eventData, msg)) {  // 写入事件数据HDF_LOGE("fail to write event data");HdfSbufRecycle(eventData);return HDF_FAILURE;}break;case 2:HDF_LOGI("Handling command 2");// 处理命令 2 的逻辑break;default:HDF_LOGE("Unknown command code: %d", cmdCode);return HDF_ERR_INVALID_PARAM;}// 上报事件int ret = HdfDeviceSendEvent(client->device, cmdCode, eventData);HdfSbufRecycle(eventData);  // 释放事件数据缓冲区return HDF_SUCCESS;
    }// 驱动绑定函数
    int32_t SampleDriverBind(struct HdfDeviceObject *device) {HDF_LOGI("SampleDriverBind called");if (device == NULL) {HDF_LOGE("Invalid device object");return HDF_FAILURE;}// 定义服务接口static struct ISampleDriverService sampleDriverA = {.ioService.Dispatch = SampleDriverDispatch,.ServiceA = SampleDriverServiceA,.ServiceB = SampleDriverServiceB,};// 将服务接口绑定到设备对象device->service = (struct IDeviceIoService *)&sampleDriverA;return HDF_SUCCESS;
    }// 驱动卸载函数
    void SampleDriverUnload(struct HdfDeviceObject *device) {HDF_LOGI("SampleDriverUnload called");// 在这里释放资源或执行清理操作
    }// 驱动描述符
    struct HdfDriverEntry g_sampleDriver = {.moduleVersion = 1,.Bind = SampleDriverBind,.Unload = SampleDriverUnload,.moduleName = "sample_driver",
    };// 驱动模块入口
    SYSEXPORT_DRIVER(g_sampleDriver);
    
  4. 驱动定义消息处理函数中的cmd类型

    #define SAMPLE_WRITE_READ 1    // 读写操作码1
    
  5. 用户态获取服务接口并发送消息到驱动

    int SendMsg(const char *testMsg)
    {if (testMsg == NULL) {HDF_LOGE("test msg is null");return HDF_FAILURE;}struct HdfIoService *serv = HdfIoServiceBind("sample_driver");// 绑定到驱动服务if (serv == NULL) {HDF_LOGE("fail to get service");return HDF_FAILURE;}struct HdfSBuf *data = HdfSbufObtainDefaultSize();// 分配数据和响应缓冲区if (data == NULL) {HDF_LOGE("fail to obtain sbuf data");return HDF_FAILURE;}struct HdfSBuf *reply = HdfSbufObtainDefaultSize();if (reply == NULL) {HDF_LOGE("fail to obtain sbuf reply");ret = HDF_DEV_ERR_NO_MEMORY;goto out;}if (!HdfSbufWriteString(data, testMsg)) {// 写入数据到数据缓冲区HDF_LOGE("fail to write sbuf");ret = HDF_FAILURE;goto out;}int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);// 调用服务的 Dispatch 函数发送请求if (ret != HDF_SUCCESS) {HDF_LOGE("fail to send service call");goto out;}
    out:HdfSbufRecycle(data);HdfSbbufRecycle(reply);HdfIoServiceRecycle(serv);return ret;
    }
    
  6. 用户态接收该驱动上报的消息

    //用户态编写驱动上报消息的处理函数。
    static int OnDevEventReceived(void *priv,  uint32_t id, struct HdfSBuf *data)
    {OsalTimespec time;OsalGetTime(&time);HDF_LOGI("%{public}s received event at %{public}llu.%{public}llu", (char *)priv, time.sec, time.usec);const char *string = HdfSbufReadString(data);if (string == NULL) {HDF_LOGE("fail to read string in event data");return HDF_FAILURE;}HDF_LOGI("%{public}s: dev event received: %{public}d %{public}s",  (char *)priv, id, string);return HDF_SUCCESS;
    }
    //用户态注册接收驱动上报消息的操作方法。
    int RegisterListen()
    {struct HdfIoService *serv = HdfIoServiceBind("sample_driver");if (serv == NULL) {HDF_LOGE("fail to get service");return HDF_FAILURE;}static struct HdfDevEventlistener listener = {.callBack = OnDevEventReceived,.priv ="Service0"};if (HdfDeviceRegisterEventListener(serv, &listener) != 0) {HDF_LOGE("fail to register event listener");return HDF_FAILURE;}......HdfDeviceUnregisterEventListener(serv, &listener);HdfIoServiceRecycle(serv);return HDF_SUCCESS;
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/70647.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leaflet实现历史轨迹播放效果

效果图如下&#xff1a; 效果实现&#xff1a; 1、添加完整轨迹线&#xff0c;蓝色的 this.echoLine L.polyline(points, { weight: 8 }).addTo(this.map) 2、添加实时轨迹线&#xff0c;初始状态置空 this.realEchoLine L.polyline([], { weight: 12, color: "#FF9…

JAVAEE一>Spring IoC和DI详解

目录 Spring容器说明&#xff1a;Ioc容器优势&#xff1a;DI介绍&#xff1a;从Spring获取对象&#xff1a;获取对象的方法&#xff1a;关于上下文的概念&#xff1a; Controller注解&#xff08;控制层&#xff1a;接收参数并响应&#xff09;&#xff1a;Service注解&#xf…

(四)趣学设计模式 之 原型模式!

目录 一、 啥是原型模式&#xff1f;二、 为什么要用原型模式&#xff1f;三、 原型模式怎么实现&#xff1f;四、 原型模式的应用场景五、 原型模式的优点和缺点六、 总结 &#x1f31f;我的其他文章也讲解的比较有趣&#x1f601;&#xff0c;如果喜欢博主的讲解方式&#xf…

完美解决:.vmx 配置文件是由 VMware 产品创建,但该产品与此版 VMware Workstation 不兼容

参考文章&#xff1a;该产品与此版 VMware Workstation 不兼容&#xff0c;因此无法使用 问题描述 当尝试使用 VMware Workstation 打开别人的虚拟机时&#xff0c;可能会遇到以下报错&#xff1a; 此问题常见于以下场景&#xff1a; 从其他 VMware 版本&#xff08;如 ESX…

从零开始的网站搭建(以照片/文本/视频信息通信网站为例)

本文面向已经有一些编程基础&#xff08;会至少一门编程语言&#xff0c;比如python&#xff09;&#xff0c;但是没有搭建过web应用的人群&#xff0c;会写得尽量细致。重点介绍流程和部署云端的步骤&#xff0c;具体javascript代码怎么写之类的&#xff0c;这里不会涉及。 搭…

【Java项目】基于SpringBoot的【高校校园点餐系统】

【Java项目】基于SpringBoot的【高校校园点餐系统】 技术简介&#xff1a;采用Java技术、MySQL数据库、B/S结构实现。 系统简介&#xff1a;高校校园点餐系统是一个面向高校师生的在线点餐平台&#xff0c;主要分为前台和后台两大模块。前台功能模块包括&#xff08;1&#xff…

Django check_password原理

check_password 是 Django 提供的一个用于密码校验的函数&#xff0c;它的工作原理是基于密码哈希算法的特性。 Django 的 make_password 函数在生成密码哈希时&#xff0c;会使用一个随机的 salt&#xff08;盐值&#xff09;。这个 salt 会与密码一起进行哈希运算&#xff0…

Vulnhun靶机-kioptix level 4-sql注入万能密码拿到权限ssh连接利用mysql-udf漏洞提权

目录 一、环境搭建信息收集扫描ip扫描开放端口扫描版本服务信息指纹探测目录扫描 二、Web渗透sql注入 三、提权UDF提权修改权限 一、环境搭建 然后选择靶机所在文件夹 信息收集 本靶机ip和攻击机ip 攻击机&#xff1a;192.168.108.130 靶机&#xff1a;192.168.108.141 扫描…

PHP 会话(Session)实现用户登陆功能

Cookie是一种在客户端和服务器之间传递数据的机制。它是由服务器发送给客户端的小型文本文件&#xff0c;保存在客户端的浏览器中。每当浏览器向同一服务器发送请求时&#xff0c;它会自动将相关的Cookie信息包含在请求中&#xff0c;以便服务器可以使用这些信息来提供个性化的…

推荐几款SpringBoot项目手脚架

作为程序员、一般需要搭建项目手脚架时、都会去Gitee或Github上去找、但是由于Github在国内并不稳定、所以就只能去Gitee去上查找。 不同语言检索方式不一样、但是也类似。 Gitee WEB应用开发 / 后台管理框架 芋道源码 ELADMIN 后台管理系统 一个基于 Spring Boot 2.7.1…

医院安全(不良)事件上报系统源码,基于Laravel8开发,依托其优雅的语法与强大的扩展能力

医院安全&#xff08;不良&#xff09;事件上报系统源码 系统定义&#xff1a; 规范医院安全&#xff08;不良&#xff09;事件的主动报告&#xff0c;增强风险防范意识&#xff0c;及时发现医院不良事件和安全隐患&#xff0c;将获取的医院安全信息进行分析反馈&#xff0c;…

H3C交换机路由器防火墙FTP/TFTP服务器搭建。

软件介绍。 3CDaemon 2.0 - Download 3CDaemon 是一款集成了多种网络服务功能的工具软件&#xff0c;主要用于网络管理和文件传输&#xff0c;支持TFTP、FTP、Syslog等多种协议&#xff0c;广泛应用于网络设备的配置和管理。 1. 主要功能 TFTP服务器&#xff1a;支持TFTP协议…

【网络安全 | 漏洞挖掘】账户接管+PII+原漏洞绕过

文章目录 前言正文前言 本文涉及的所有漏洞测试共耗时约三周,成果如下: 访问管理面板,成功接管目标列出的3000多家公司。 获取所有员工的真实指纹、机密文件及个人身份信息(PII)。 绕过KYC认证,成功接管电话号码。 绕过此前发现的漏洞。 正文 在测试目标时,我发现了一…

深度学习学习笔记(34周)

目录 摘要 Abstracts 简介 Hourglass Module&#xff08;Hourglass 模块&#xff09; 网络结构 Intermediate Supervision&#xff08;中间监督&#xff09; 训练过程细节 评测结果 摘要 本周阅读了《Stacked Hourglass Networks for Human Pose Estimation》&#xf…

JVM类文件结构深度解析:跨平台基石与字节码探秘

目录 一、类文件&#xff1a;Java生态的通用语言 1.1 字节码的桥梁作用 1.2 类文件核心优势 二、类文件二进制结构剖析 2.1 整体结构布局 2.2 魔数与版本控制 2.3 常量池&#xff1a;类文件的资源仓库 2.4 访问标志位解析 三、核心数据结构详解 3.1 方法表结构 3.2 …

wps中zotero插件消失,解决每次都需要重新开问题

参考 查看zotero目录 D:\zotero\integration\word-for-windows 加载项点击 dotm即可 长期解决 把dom 复制到 C:\Users\89735\AppData\Roaming\kingsoft\office6\templates\wps\zh_CN还是每次都需要重新开的话 重新加载一下

List 接口中的 sort 和 forEach 方法

List 接口中的 sort 和 forEach 方法是 Java 8 引入的两个非常实用的函数&#xff0c;分别用于 排序 和 遍历 列表中的元素。以下是它们的详细介绍和用法&#xff1a; sort 函数 功能 对列表中的元素进行排序。 默认使用自然顺序&#xff08;如数字从小到大&#xff0c;字符…

GitCode 助力至善云学:构建智慧教育平台

项目仓库&#xff1a; 前端&#xff1a;https://gitcode.com/Fer_Amiya/vue-ZhiShanYunXue-Client 后端&#xff1a;https://gitcode.com/Fer_Amiya/go-ZhiShanYunXue-Server 突破传统教学困境&#xff0c;探索教育新解法 传统教学的习题讲评环节&#xff0c;教师面临着难以…

nnUNet V2修改网络——加入MultiResBlock模块

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 MultiRes Block 是 MultiResUNet 中核心组件之一,旨在解决传统 U-Net 在处理多尺度医学图像时的局…

HarmonyOS 开发套件 介绍——下篇

HarmonyOS 开发套件 介绍——下篇 在HarmonyOS的生态中&#xff0c;开发套件作为支撑整个系统发展的基石&#xff0c;为开发者提供了丰富而强大的工具和服务。本文将深入继续介绍HarmonyOS SDK、ArkCompiler、DevEco Testing、AppGallery等核心组件&#xff0c;帮助开发者全面掌…