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

gooood谷德设计网站广告做到百度第一页

gooood谷德设计网站,广告做到百度第一页,网站做信息流,网站建设app开发学习在分析openharmony的hdf框架的设备驱动加载器(IDriverLoader)时发现在创建实例时会首先判断一下是否完成了驱动入口的构建(HdfDriverEntryConstruct),如果没有构建会重新构建,这与我开始以为的不一致(我一直以为是采用的linux内核方式,只是由…

在分析openharmony的hdf框架的设备驱动加载器(IDriverLoader)时发现在创建实例时会首先判断一下是否完成了驱动入口的构建(HdfDriverEntryConstruct),如果没有构建会重新构建,这与我开始以为的不一致(我一直以为是采用的linux内核方式,只是由hdf来将驱动注册进去),oh将这部分由hdf框架接管了。下面我便将这部分实现驱动程序的动态加载和管理的技术细节进行分析。

实现驱动程序的动态加载和管理主要过程如下:

  • 驱动注册通过 HDF_DRIVER_INIT 宏将驱动入口点注册.hdf.driver 段。
  • 驱动加载:由设备管理器解析配置文件并调用驱动的 BindInit 函数
  • 服务发布与订阅:通过 HdfDeviceNodePublishServiceHdfDeviceSubscribeService 实现。
  • 驱动卸载:通过 Release 函数释放驱动资源

在使用前首先看下驱动是如何应用的(有个大概的使用思路)

struct HdfDriverEntry g_i2cManagerEntry = {//驱动程序的入口信息.moduleVersion = 1,//驱动模块的版本号.Bind = I2cManagerBind,//用于将驱动与设备对象关联.Init = I2cManagerInit,//用于完成驱动的初始化操作.Release = I2cManagerRelease,//用于释放驱动占用的资源.moduleName = "HDF_PLATFORM_I2C_MANAGER", //必须与 device_info.hcs 文件中的设备名称一致
};
HDF_INIT(g_i2cManagerEntry);//用于将驱动程序的入口结构注册到 HDF 框架中

下面分别介绍动态加载和管理的四个主要过程。

驱动注册

在 OpenHarmony 中,驱动程序通过 HDF_INIT宏注册到 .hdf.driver 段中。这个宏将驱动程序的入口点信息存储到特定的内存段,供运行时加载

在hdf_core\interfaces\inner_api\host\shared\hdf_device_desc.h文件中我们可以看到实际HDF_INIT宏实际调用的为HDF_DRIVER_INIT。

#define HDF_INIT(module)  HDF_DRIVER_INIT(module)
  • HDF_DRIVER_INIT说明

结合hdf_core\framework\core\common\include\host\hdf_device_section.h代码的宏定义

//这用于确保驱动程序的入口点不会被编译器优化掉
#define USED_ATTR __attribute__((used))//用于将变量或函数放置到指定的内存段(section)中
//将驱动程序的入口点信息存储到 .hdf.driver 段中
//这个段在运行时会被 HDF 框架扫描,以获取驱动程序的入口点
#define HDF_SECTION __attribute__((section(".hdf.driver")))

可得注册一个驱动程序模块

#define HDF_DRIVER_INIT(module) \const size_t USED_ATTR module##HdfEntry HDF_SECTION = (size_t)(&(module))

定义一个全局变量(module##HdfEntry),其名称由驱动模块名(module)拼接而成。使用 USED_ATTR 确保该变量不会被优化掉。使用 HDF_SECTION 将该变量放置到 .hdf.driver 段中。将该变量的值设置为驱动模块的地址(&(module))。这样,驱动程序的入口点信息就会被存储到 .hdf.driver 段中,供运行时扫描和加载。

此时便有个疑问,我们只知道驱动程序的入口点信息就会被存储到 .hdf.driver 段中,那我们如何访问或使用它呢?

答案就在hdf_core\framework\core\common\include\host\hdf_device_section.h文件中的以下两个函数中

/*** 这个宏定义用于获取指定变量的地址。* 声明一个外部变量(extern type name)。* 返回该变量的地址(&(name))。* 这个宏主要用于定义 _hdf_drivers_start 和 _hdf_drivers_end,标记驱动程序入口点的范围。*/
#define HDF_DRIVER_SEC_NAME(type, name) \({extern type name;            \&(name);                       \})/**通过 HDF_DRIVER_SEC_NAME 宏,获取 _hdf_drivers_start 和 _hdf_drivers_end 的地址。
这些地址在运行时被 HDF 框架用来遍历 .hdf.driver 段中的驱动程序入口点。
HDF 框架可以通过 _hdf_drivers_start 和 _hdf_drivers_end 之间的范围,动态加载所有注册的驱动程序。
*/
#define HDF_DRIVER_BEGIN() HDF_DRIVER_SEC_NAME(size_t, _hdf_drivers_start)
#define HDF_DRIVER_END() HDF_DRIVER_SEC_NAME(size_t, _hdf_drivers_end)

经过对上述代码的理解我们知道如何来使用了,但是此时还有一个疑问没有解决,**那就是_hdf_drivers_start和_hdf_drivers_end变量在哪定义的呢?它在哪被赋值了呢?**通过对代码的搜索可以看到在链接器脚本(vmlinux.lds.S)中有相关定义。如下图所示:

在这里插入图片描述

这段代码的作用是:

  1. 定义一个名为 .init.hdf_table 的段
  2. 该段的起始位置设置 _hdf_drivers_start 符号
  3. 所有标记为 .hdf.driver 的数据(即驱动程序入口点)放入该段。
  4. 在该段的结束位置设置 _hdf_drivers_end 符号

这部分的内容有点绕为了更好的总结在这儿弄了个使用demo,可以供参考理解:

// 定义一个驱动程序模块
struct HdfDriverEntry MyDriver;// 注册驱动程序模块
HDF_DRIVER_INIT(MyDriver);// 在代码中使用 HDF_DRIVER_BEGIN 和 HDF_DRIVER_END 获取驱动程序范围
size_t *start = HDF_DRIVER_BEGIN();
size_t *end = HDF_DRIVER_END();// 遍历驱动程序入口点
for (size_t *ptr = start; ptr < end; ptr++) {struct HdfDriverEntry *driver = (struct HdfDriverEntry *)(*ptr);// 加载驱动程序
}

驱动加载

驱动加载过程由 HDF 框架的设备管理器(Device Manager)和设备主机(Device Host)协同完成,这部分详细的过程比较复杂(本周应该能写完这篇汇总的),此处只列出核心点

  • 设备管理器初始化

    static int __init DeviceManagerInit(void)
    {int ret = DeviceManagerStart();if (ret < 0) {HDF_LOGE("%s start failed %d", __func__, ret);} else {HDF_LOGD("%s start success", __func__);}return ret;
    }
    late_initcall(DeviceManagerInit);
    

    设备管理器在系统启动时通过 late_initcall 初始化,并开始加载驱动。

  • 驱动加载流程

    1. 设备管理器解析配置文件(device_info.hcs),获取设备和驱动的映射关系
    2. 根据配置文件中的 preload 字段,决定驱动是按需加载还是按序加载
    3. 遍历 .hdf.driver 段,获取驱动程序的入口地址
    4. 调用驱动的 BindInit 函数完成初始化

代码调用过程如下:
在这里插入图片描述

int HdfDeviceLaunchNode(struct HdfDeviceNode *devNode)
{const struct HdfDriverEntry *driverEntry = devNode->driver->entry;int ret = DeviceDriverBind(devNode);if (ret != HDF_SUCCESS) {return ret;}ret = driverEntry->Init(&devNode->deviceObject);if (ret != HDF_SUCCESS) {return HDF_DEV_ERR_DEV_INIT_FAIL;}ret = HdfDeviceNodePublishService(devNode);if (ret != HDF_SUCCESS) {return HDF_DEV_ERR_PUBLISH_FAIL;}return ret;
}

服务发布与订阅

HDF 框架支持服务发布和订阅机制,允许驱动程序在初始化后发布服务接口,供其他模块使用

  • 服务发布

    int HdfDeviceNodePublishService(struct HdfDeviceNode *devNode);
    
  • 服务订阅

其他模块可以通过 HdfDeviceSubscribeService 订阅驱动服务。当驱动加载完成后,框架会将服务接口发布给订阅者

int HdfDeviceSubscribeService(struct HdfDeviceObject *deviceObject, const char *serviceName, struct SubscriberCallback callback);

对此部分内容需要详细了解的可以参考

驱动卸载

和驱动加载相对应的卸载驱动的函数为HdfDeviceUnlaunchNode,当驱动被卸载或初始化失败时,HDF 框架会调用驱动的 Release 函数释放资源:

static void HdfDeviceUnlaunchNode(struct HdfDeviceNode *devNode)
{....if (devNode->driver != NULL) {driverEntry = devNode->driver->entry;//从设备节点中获取驱动程序对象(devNode->driver)}if (driverEntry != NULL && driverEntry->Release != NULL) {driverEntry->Release(&devNode->deviceObject);//如果驱动程序的入口结构和 Release 函数指针都有效,调用 Release 函数释放驱动占用的资源,即驱动中传入的release函数}....
}
http://www.hkea.cn/news/604748/

相关文章:

  • 扁平式网站模板b2b网站推广优化
  • 做外贸网站网络营销咨询服务
  • 江门网站建设方案报价淘宝seo优化怎么做
  • 盘龙城做网站推广网站推广
  • 如何做电子书网站域名站长工具
  • 物联网平台有哪些排名优化外包公司
  • 秦皇岛汽车网站制作数字营销工具
  • 培训教育的网站怎么做东莞做网站的联系电话
  • 云南做网站的公司外贸谷歌优化
  • 网页设计学徒培训可试学巢湖seo推广
  • 让顾客心动的句子seo模拟点击软件源码
  • 设计类专业包括哪些kj6699的seo综合查询
  • 手机网站制作哪家好查关键词
  • 米拓企业网站管理系统电商培训机构排名前十
  • 做效果图有哪些网站seo点击排名
  • 网络营销推广网站收录seo推广排名平台有哪些
  • 产品经理如何看待网站开发广州软件系统开发seo推广
  • wordpress 忘记管理员如何做网站seo
  • app和网站哪个有优势淘宝关键词排名
  • wordpress该域名宁波网站seo公司
  • 建购物网站怎么建呀简单的网站建设
  • 江苏省建设教育协会网站首页百度知道合伙人答题兼职入口
  • 做优化的网站平台搭建
  • 做网站需要多久网络推广是什么专业
  • 厦门加盟网站建设线上推广营销
  • 定制网站案例seo搜索引擎优化薪酬
  • 网站制作成功后怎么使用浏览器观看b站视频的最佳设置
  • 一家专门做开网店的网站北京seo专员
  • 专业企业网站搭建服务头条权重查询
  • 去哪儿网站上做民宿需要材料免费的黄冈网站有哪些平台