0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浅析HarmonyOS驱动加载过程

电子工程师 来源:HarmonyOS开发者 作者:chenfeng,yuanbo 2021-05-18 11:55 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1

HarmonyOS驱动概述

HarmonyOS驱动框架采用C语言面向对象编程模型构建,通过平台解耦、内核解耦,来达到兼容不同内核,统一平台底座的目的,从而帮助开发者实现驱动的“一次开发、多系统部署”。 为了达成这个目标, HarmonyOS驱动框架提供了:1. 操作系统适配层(OSAL,operating system abstraction layer):提供内核操作相关接口进行统一封装,屏蔽不同系统操作接口。

2.平台驱动接口:提供Board部分驱动(例如:I2C/SPI/UART总线等平台资源)支持,同时对Board硬件操作接口进行统一的适配抽象,开发者只需开发新硬件抽象接口,即可获得新增Board部分驱动支持。

3.驱动模型:面向器件驱动,提供常见的驱动抽象模型,主要达成两个目的:

1)提供标准化的器件驱动,开发者无需独立开发,通过配置即可完成驱动的部署。

2)提供驱动模型抽象,屏蔽驱动与不同系统组件间的交互,使得驱动更具备通用性。

为了进一步简化HarmonyOS驱动开发,HarmonyOS驱动框架支持多种驱动加载方式:

1.支持驱动动态加载和静态加载,解除驱动代码和框架间的直接代码依赖,使得驱动程序可以独立编译和部署;

2.支持按需动态加载方式,避免设备驱动全量加载,可有效降低系统资源的占用。 本文主要分析HarmonyOS驱动加载过程,在正式介绍之前,首先了解HarmonyOS驱动架构的组成、工作原理和机制,从而了解驱动加载的细节。

●官网相关介绍:

https://device.harmonyos.com/cn/docs/develop/drive/oem_drive_hdfdev-0000001051715456

2

HarmonyOS驱动架构介绍

2.1 HarmonyOS驱动架构组成

085f72c6-b567-11eb-bf61-12bb97331649.png

图1 HarmonyOS驱动架构

HarmonyOS驱动架构主要由HDF驱动框架、驱动程序、驱动配置文件和驱动接口四个部分组成。

1)HDF驱动框架提供统一的硬件资源管理,驱动加载管理以及设备节点管理等功能。驱动框架采用的是主从模式设计,由Device Manager和Device Host组成。

Device Manager提供了统一的驱动管理,Device Manager启动时根据Device Information提供驱动设备信息加载相应的驱动Device Host,并控制Host完成驱动的加载。

Device Host提供驱动运行的环境,同时预置Host Framework与Device Manager进行协同,完成驱动加载和调用。根据业务的需求Device Host可以有多个实例。

说明

◆ Device Host顾名思义就是驱动宿主,提供驱动运行的环境。

◆ 当驱动部署在用户态时,Device Host可以由独立的进程进行承载。

◆ 当驱动在部署在内核态时,Device Host仅表示逻辑隔离。

◆ Device Host的划分原则:Device Host属于一类设备聚合,如Camera、Audio、Display等。

◆ 驱动程序是部署在一个Device Host还是部署在不同的Device Host,主要考虑驱动程序之间是否存在业务耦合性,如果两个驱动程序之间存在依赖,可以考虑将这部分驱动程序部署在统一Host。

2)驱动程序实现驱动的具体功能,每个驱动由一个或者多个驱动程序组成,每个驱动程序都对应着一个Driver Entry。Driver Entry主要完成驱动的初始化和驱动接口绑定功能。

3)驱动配置文件.hcs主要由设备信息(Device Information)和设备资源(Device Resource)组成。Device Information完成设备信息的配置,如配置接口发布策略,驱动加载的方式等。Device Resource完成设备资源的配置,如GPIO管脚、寄存器等资源信息的配置。

4)驱动接口HDI(Hardware Driver interface)提供标准化的接口定义和实现,驱动框架提供IO Service和IO Dispatcher机制,使得不同部署形态下驱动接口趋于形式一致。

当驱动部署在RTOS(Real-Time Operating System)轻量化操作系统时,驱动接口和驱动程序之间采用的是Function Call方式调用,因此驱动接口仅提供定义,驱动接口实现由驱动程序提供。

2.2 HDF驱动框架工作原理

0873dc7a-b567-11eb-bf61-12bb97331649.png

图2 HDF驱动框架工作原理

Device Manager提供了统一的驱动加载管理机制和驱动接口发布机制。当Device Host环境加载完成时,Device Manager根据Device Information信息,请求Host加载相应的驱动程序,Device Host在收到请求时,进行以下操作:

1)根据请求加载设备信息,查找并加载指定路径下驱动镜像或从指定段地址(section)查找驱动程序入口;

2)查找驱动设备描述符,匹配对应的设备驱动;

3)当驱动匹配成功时,加载指定驱动程序镜像;

4)Host Framework在驱动镜像加载成功后,调用驱动程序(Driver Entry)的绑定接口和初始化接口,实现与驱动程序的服务对象绑定,同时初始化设备驱动程序;

5)当Device Information的配置中的服务策略要求对外暴露驱动接口时,驱动框架就将驱动程序的服务对象添加到对外发布的服务对象列表中,外部客户端程序就可以通过此列表来查询并访问相应的服务接口。

2.3 驱动接口工作机制

08a5212c-b567-11eb-bf61-12bb97331649.png

图3 驱动接口工作机制

驱动接口主要存在以下几种实现:

•当驱动以内核组件部署时,客户端程序访问驱动程序需要通过system call方式调用,驱动接口通过IO Service请求将消息通过system call方式调用到内核,并将消息分发到IO Dispatcher处理。

•当驱动以用户态服务形式部署时,客户端进程访问驱动进程需要通过IPC方式通信,IO Service完成IPC通信的客户端消息请求封装,IO Dispatcher完成驱动服务端消息请求封装,客户端消息通过IPC通信到达服务端并分发给IO Dispatcher处理。

为了使客户端和服务端驱动调用方式基本一致,驱动框架提供IO Service和IO Dispatcher机制屏蔽了调用消息传递方式的差异。

驱动接口实现统一采用远程调用方式,客户端驱动接口函数将请求序列化成内存数据,通过驱动框架提供的IO Service将消息发送到服务端处理,服务端在收到请求消息时通过IO Dispatcher机制将消息分发给消息处理函数处理,处理函数将反序列化内存数据解析成相应的请求。这样做的好处是,开发者只需重点关注接口的定义,无需过多关注如何实现不同平台上接口适配。

3

驱动加载过程分析

HarmonyOS驱动根据部署的不同方式,存在两种驱动加载方式:•动态加载方式:采用传统的so(共享库) 加载方式,驱动程序通过指定Symbol找到驱动函数入口进行加载。•静态加载方式:采用将驱动程序通过Scatter编译方式,编译到指定的Section,再通过访问指定Section对应的地址,找到驱动函数入口进行加载。 下面结合一个Sample示例代码,讲解驱动加载过程,重点分析静态加载方式下内核态驱动加载过程。

3.1 实现驱动程序初始化接口

在HDF驱动框架中,HdfDriverEntry对象被用来描述一个驱动实现。

struct HdfDriverEntry { int32_t moduleVersion; const char *moduleName; int32_t (*Bind)(struct HdfDeviceObject *deviceObject); int32_t (*Init)(struct HdfDeviceObject *deviceObject); void (*Release)(struct HdfDeviceObject *deviceObject);};

(左右滑动查看更多)

编写一个简单的驱动,首先需要实现驱动程序(Driver Entry)入口中的三个主要接口:•Bind接口:实现驱动接口实例化绑定,如果需要发布驱动接口,会在驱动加载过程中被调用,实例化该接口的驱动服务并和DeviceObject绑定。•Init接口:实现驱动的初始化,返回错误将中止驱动加载流程。•Release接口:实现驱动的卸载,在该接口中释放驱动实例的软硬件资源。

int SampleDriverBind(struct HdfDeviceObject *deviceObject){ HDF_LOGE(“SampleDriverBind enter!”); static struct IDeviceIoService testService = { .Dispatch = SampleServiceDispatch, .Open = NULL, .Release = NULL, }; 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);

(左右滑动查看更多)

3.2 导出驱动程序入口符号

实现驱动程序初始化后,需要将驱动程序入口通过驱动声明宏导出,这样驱动框架才能在启动时识别到驱动程序的存在,驱动才能被加载:

#define HDF_INIT(module) HDF_DRIVER_INIT(module)

(左右滑动查看更多)

这里将HDF_INIT宏展开:

#define HDF_SECTION __attribute__((section(“.hdf.driver”)))#define HDF_DRIVER_INIT(module) const size_t USED_ATTR module##HdfEntry HDF_SECTION = (size_t)(&(module))

(左右滑动查看更多)

下面是实现原理:

08d92828-b567-11eb-bf61-12bb97331649.png

图4 Driver Entry内存分布

可以看到HDF_INIT宏是定义了一个“驱动模块名+HdfEntry”的符号放到“.hdf.driver” 所在section,该符号指向的内存地址即为驱动程序入口结构体的地址。这个特殊的section将用于开机启动时查找设备驱动。

3.3 添加设备配置

在设备对应的device_info.hcs添加sample驱动的配置:

sample_host :: host { hostName = “sample_host”; sample_device :: device { device0 :: deviceNode { policy = 2; priority = 100; preload = 1; permission = 0664; moduleName = “sample_driver”; serviceName = “sample_service”; } }}

(左右滑动查看更多)

在配置中定义的device将在加载过程中产生一个设备实例,通过moduleName字段指定设备对应的驱动名称,从而将设备与驱动关联起来。其中,设备与驱动可以是一对多的关系,即可以实现一个驱动支持多个同类型设备。

3.4 驱动启动过程

我们添加的驱动是如何被执行的呢?简单来说,在系统启动时,驱动框架先启动,通过解析配置文件获取到设备列表,通过读取“.hdf.driver”段读取到驱动程序(Driver Entry)列表,然后遍历设备列表与驱动程序列表进行匹配,并加载匹配成功的驱动。

驱动框架有两大核心管理者:•DeviceManager:负责设备的管理,包括设备加载、卸载和查询等设备相关功能。•DeviceServiceManager:负责管理设备发布的接口服务,提供接口服务的发布和查询等功能。

驱动加载主要由DeviceManager主导,首先DeviceManager要解析配置文件中的Host列表,根据Host列表中的信息来实例化对应的Host对象。Host解析配置文件获取到关联的设备列表,遍历设备列表去获取与之匹配的驱动程序名称,然后基于驱动程序名称遍历前面提到的“.hdf.driver” section获得驱动程序地址。

下面介绍具体过程。

3.4.1 获取设备列表

0902f0ae-b567-11eb-bf61-12bb97331649.png

图5 设备列表结构

配置文本编译后会变成二进制格式的配置文件,其中设备相关信息被存放在一个用“hdf_manager”标记的device_info配置块中,host的内容以块的形式在device_info块中依次排列,host块中记录了host名称、启动优先级和设备列表信息。设备信息中的moduleName字段将用于和驱动程序入口中的moduleName进行匹配,从而为设备匹配到正确的驱动程序。

3.4.2 获取驱动程序列表

091ba69e-b567-11eb-bf61-12bb97331649.png

图6 驱动程序(DriverEntry)内存布局

HDF驱动框架通过驱动程序入口符号的地址集中存放到一个特殊的section来实现对驱动的索引,这个section的开头和末尾插入了_hdf_drivers_start、_hdf_drivers_end两个特殊符号,用于标记这个section的范围,两个特殊符号之间的数据即为驱动实现指针。

3.4.3 驱动程序加载流程

09381dce-b567-11eb-bf61-12bb97331649.png

图7 HDF驱动加载流程

Device Manager遍历设备列表,当查找到对应驱动实现时,为设备创建Device对象实例,如果设备配置中的policy字段为需要对外发布驱动接口(SERVICE_POLICY_CAPACITY),那么驱动的Bind接口将首先被调用,用于关联设备和服务实例。然后驱动的Init接口将被调用,用于完成驱动的相关初始化工作。如果驱动被卸载或者因为硬件等原因Init接口返回失败,Release将被调用,用于释放驱动申请的各类资源。

4

总结

本次和大家分享了HarmonyOS驱动的主要设计思想,重点分析了内核态驱动加载的过程,关于HarmonyOS驱动其他内容,后续会有更多技术文章向大家持续分享,敬请期待。

作者:chenfeng,yuanbo,华为驱动工程师

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动接口
    +关注

    关注

    0

    文章

    10

    浏览量

    2761
  • HarmonyOS
    +关注

    关注

    80

    文章

    2147

    浏览量

    35623
  • HDF框架
    +关注

    关注

    0

    文章

    10

    浏览量

    2986
  • OpenHarmony
    +关注

    关注

    31

    文章

    3928

    浏览量

    20740

原文标题:HarmonyOS驱动加载过程分析

文章出处:【微信号:HarmonyOS_Dev,微信公众号:HarmonyOS开发者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    图扑软件 3D 场景预加载应用实现

    加载是在进入正式场景之前提前加载所需模型、材质、图片等资源的技术手段,其核心价值在于消除资源加载等待,确保场景首次渲染即可完整呈现,从而提供无缝、流畅的用户体验。在复杂的 Web 3D 可视化
    的头像 发表于 12-01 16:04 99次阅读
    图扑软件 3D 场景预<b class='flag-5'>加载</b>应用实现

    HarmonyOS 5 入门系列 】鸿蒙HarmonyOS示例项目讲解

    HarmonyOS 5 入门系列 】鸿蒙HarmonyOS示例项目讲解 ##鸿蒙开发能力 ##HarmonyOS SDK应用服务##鸿蒙金融类应用 (金融理财# 一、前言:移动开发声明式 UI
    的头像 发表于 07-07 11:57 829次阅读
    【 <b class='flag-5'>HarmonyOS</b> 5 入门系列 】鸿蒙<b class='flag-5'>HarmonyOS</b>示例项目讲解

    HarmonyOS Next】ArkUI-X休闲益智接水果【进阶】

    本文通过ArkUI-X实现跨平台接水果游戏,深入探究网络图片在HarmonyOS与iOS设备上的渲染差异,并提供专业级优化方案。基于WebView的混合架构,我们实现了单代码库双端适配的高效开发
    发表于 06-28 22:14

    HarmonyOS next】ArkUI-X休闲益智记忆翻牌【进阶】

    本文通过记忆翻牌游戏实现,揭秘网络图片在HarmonyOS与iOS设备上的渲染差异,并提供专业级优化方案。基于ArkUI-X的Web组件技术,我们实现了一套代码双端运行的混合架构。 一、跨平台
    发表于 06-28 22:12

    HarmonyOS NEXT应用元服务布局优化长列表使用懒加载与组件复用

    超过两屏的列表情况,并且当内容布局相对固定的情况下,配合组件复用的方式来减少滑动过程中的组件创建。在长列表加载性能优化中,介绍了较为详细的实践案例,这里我们仅引用一些关键性能收益数据。 懒加载 针对
    发表于 06-27 16:08

    HarmonyOS入门指南

    1、文档与教程 HarmonyOS开发文档-应用开发导读 OpenHarmony--应用开发导读 仓颉编程语言官网 华为开发者博客 华为开发者问答专区 华为生态市场-鸿蒙生态市场
    的头像 发表于 06-27 00:11 597次阅读

    同步电机失步浅析

    纯分享帖,需要者可点击附件免费获取完整资料~~~*附件:同步电机失步浅析.pdf【免责声明】本文系网络转载,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请第一时间告知,删除内容!
    发表于 06-20 17:42

    HarmonyOS优化应用预置图片资源加载耗时问题性能优化

    提升要从收益和开销两部分进行分析: 1.收益 纹理压缩的主要收益是在编译过程中将预置图片转换为纹理格式,能直接被GPU读取进行渲染,降低了CPU和DDR的负载,能更快的加载图片。在Tab栏切换示例中将
    发表于 05-29 16:11

    HarmonyOS5云服务技术分享--应用预加载提速指南

    手把手教你用预加载优化应用启动速度 Hi,开发者朋友们!今天我们来聊聊如何通过预加载技术让应用启动快人一步。在用户体验至上的时代,首屏加载速度直接关系到用户留存率,快来掌握这个提升性能的利器吧! 一
    发表于 05-22 20:39

    HarmonyOS5云服务技术分享--云函数预加载文章整理

    无缝对接HarmonyOS应用,实现预加载等高级功能。如果你在实践过程中遇到问题,欢迎在评论区留言,或到华为开发者社区提问(记得带上 #云函数 标签哦~)。 ​​最后,感谢你的耐心阅读!​​ ? 如果觉得有帮助,不妨点个赞或分享
    发表于 05-22 20:33

    HarmonyOS5云服务技术分享--ArkTS开发Node环境

    ✨ 你好呀,开发者小伙伴们!今天我们来聊聊如何在HarmonyOS(ArkTS API 9及以上)中玩转云函数,特别是结合Node.js和HTTP触发器的开发技巧。文章会手把手带你从零开始,用最接地
    发表于 05-22 17:21

    高质量 HarmonyOS 权限管控流程

    高质量 HarmonyOS 权限管控流程 在 HarmonyOS 应用开发过程中,往往会涉及到 敏感数据 和 硬件资源 的调动和访问,而这部分的调用就会涉及到管控这部分的知识和内容了。我们需要对它有
    的头像 发表于 04-02 18:29 1993次阅读
    高质量 <b class='flag-5'>HarmonyOS</b> 权限管控流程

    HarmonyOS NEXT 原生应用/元服务-DevEco Profiler性能优化过程

    优化是一个不断持续的周期性的过程,您需要在应用开发过程中观察应用的运行表现来识别性能瓶颈,通过运行时数据来定界定位性能问题,定位根因后修复代码并验证优化措施的可行性,循环往复直到应用满足您的性能指标
    发表于 02-19 15:28

    解决HarmonyOS应用中Image组件白块问题的有效方案

    HarmonyOS应用开发过程中,通过Image组件加载网络图片时,通常会经历四个关键阶段:组件创建、图片资源下载、图片解码和刷新。当加载的图片资源过大时,Image组件会等待图片数
    的头像 发表于 02-17 10:08 1601次阅读
    解决<b class='flag-5'>HarmonyOS</b>应用中Image组件白块问题的有效方案

    EE-240: ADSP-BF533 Blackfin加载过程

    电子发烧友网站提供《EE-240: ADSP-BF533 Blackfin加载过程.pdf》资料免费下载
    发表于 01-05 10:00 0次下载
    EE-240: ADSP-BF533 Blackfin<b class='flag-5'>加载</b><b class='flag-5'>过程</b>