智能建网站网页导航视频网站在线制作教程

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

智能建网站,网页导航视频网站在线制作教程,国际域名注册查询,网站做优化和推广哪个好在分析openharmony的hdf框架的设备驱动加载器(IDriverLoader)时发现在创建实例时会首先判断一下是否完成了驱动入口的构建(HdfDriverEntryConstruct)#xff0c;如果没有构建会重新构建#xff0c;这与我开始以为的不一致(我一直以为是采用的linux内核方式#xff0c;只是由…在分析openharmony的hdf框架的设备驱动加载器(IDriverLoader)时发现在创建实例时会首先判断一下是否完成了驱动入口的构建(HdfDriverEntryConstruct)如果没有构建会重新构建这与我开始以为的不一致(我一直以为是采用的linux内核方式只是由hdf来将驱动注册进去)oh将这部分由hdf框架接管了。下面我便将这部分实现驱动程序的动态加载和管理的技术细节进行分析。 实现驱动程序的动态加载和管理主要过程如下 驱动注册通过 HDF_DRIVER_INIT 宏将驱动入口点注册到 .hdf.driver 段。驱动加载由设备管理器解析配置文件并调用驱动的 Bind 和 Init 函数。服务发布与订阅通过 HdfDeviceNodePublishService 和 HdfDeviceSubscribeService 实现。驱动卸载通过 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中有相关定义。如下图所示: 这段代码的作用是 定义一个名为 .init.hdf_table 的段。在该段的起始位置设置 _hdf_drivers_start 符号。将所有标记为 .hdf.driver 的数据即驱动程序入口点放入该段。在该段的结束位置设置 _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 初始化并开始加载驱动。 驱动加载流程 设备管理器解析配置文件device_info.hcs获取设备和驱动的映射关系。根据配置文件中的 preload 字段决定驱动是按需加载还是按序加载。遍历 .hdf.driver 段获取驱动程序的入口地址。调用驱动的 Bind 和 Init 函数完成初始化
代码调用过程如下
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函数}…. }