HarmonyOS 驱动加载过程分析
1、HarmonyOS 驱动概述
HarmonyOS 驱动框架采用 C 语言面向对象编程模型构建,通过平台解耦、内核解耦,来
达到兼容不同内核,统一平台底座的目的,从而帮助开发者实现驱动的“一次开发、多系统
部署”。
为了达成这个目标, HarmonyOS 驱动框架提供了:
1. 操作系统适配层(OSAL,operating system abstraction layer):提供内核操作相关
接口进行统一封装,屏蔽不同系统操作接口。
2.平台驱动接口:提供 Board 部分驱动(例如:I2C/SPI/UART 总线等平台资源)支持,同
时对 Board 硬件操作接口进行统一的适配抽象,开发者只需开发新硬件抽象接口,即可获
得新增 Board 部分驱动支持。
3.驱动模型:面向器件驱动,提供常见的驱动抽象模型,主要达成两个目的:
1)提供标准化的器件驱动,开发者无需独立开发,通过配置即可完成驱动的部署。
2)提供驱动模型抽象,屏蔽驱动与不同系统组件间的交互,使得驱动更具备通用性。
为了进一步简化 HarmonyOS 驱动开发,HarmonyOS 驱动框架支持多种驱动加载方式:
来源:HarmonyOS 开发者微信号 https://mp.weixin.qq.com/s/crH9YJvG1WwTWrQ-jn__nA
1.支持驱动动态加载和静态加载,解除驱动代码和框架间的直接代码依赖,使得驱动程序可
以独立编译和部署;
2.支持按需动态加载方式,避免设备驱动全量加载,可有效降低系统资源的占用。
本文主要分析 HarmonyOS 驱动加载过程,在正式介绍之前,首先了解 HarmonyOS 驱动
架构的组成、工作原理和机制,从而了解驱动加载的细节。
●官网相关介绍:
https://device.harmonyos.com/cn/docs/develop/drive/oem_drive_hdfdev-0000001
051715456
2、HarmonyOS 驱动架构介绍
2.1 HarmonyOS 驱动架构组成
来源:HarmonyOS 开发者微信号 https://mp.weixin.qq.com/s/crH9YJvG1WwTWrQ-jn__nA
图 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,主要考虑驱动程
序之间是否存在业务耦合性,如果两个驱动程序之间存在依赖,可以考虑将这部分驱动程序
来源:HarmonyOS 开发者微信号 https://mp.weixin.qq.com/s/crH9YJvG1WwTWrQ-jn__nA
部署在统一 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 驱动框架工作原理
来源:HarmonyOS 开发者微信号 https://mp.weixin.qq.com/s/crH9YJvG1WwTWrQ-jn__nA
图 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 的配置中的服务策略要求对外暴露驱动接口时,驱动框架就将
驱动程序的服务对象添加到对外发布的服务对象列表中,外部客户端程序就可以通过此列表
来源:HarmonyOS 开发者微信号 https://mp.weixin.qq.com/s/crH9YJvG1WwTWrQ-jn__nA
来查询并访问相应的服务接口。
2.3 驱动接口工作机制
图 3 驱动接口工作机制
驱动接口主要存在以下几种实现:
•当驱动以内核组件部署时,客户端程序访问驱动程序需要通过 system call 方式调用,驱
动接口通过 IO Service 请求将消息通过 system call 方式调用到内核,并将消息分发到 IO
Dispatcher 处理。
•当驱动以用户态服务形式部署时,客户端进程访问驱动进程需要通过 IPC 方式通信,IO
Service 完成 IPC 通信的客户端消息请求封装,IO Dispatcher 完成驱动服务端消息请求封
装,客户端消息通过 IPC 通信到达服务端并分发给 IO Dispatcher 处理。
为了使客户端和服务端驱动调用方式基本一致,驱动框架提供 IO Service 和 IO Dispatcher
机制屏蔽了调用消息传递方式的差异。
驱动接口实现统一采用远程调用方式,客户端驱动接口函数将请求序列化成内存数据,通过
来源:HarmonyOS 开发者微信号 https://mp.weixin.qq.com/s/crH9YJvG1WwTWrQ-jn__nA
驱动框架提供的 IO Service 将消息发送到服务端处理,服务端在收到请求消息时通过 IO
Dispatcher 机制将消息分发给消息处理函数处理,处理函数将反序列化内存数据解析成相
应的请求。这样做的好处是,开发者只需重点关注接口的定义,无需过多关注如何实现不同
平台上接口适配。
3、驱动加载过程分析
HarmonyOS 驱动根据部署的不同方式,存在两种驱动加载方式:
•动态加载方式:采用传统的 so(共享库) 加载方式,驱动程序通过指定 Symbol 找到驱
动函数入口进行加载。
•静态加载方式:采用将驱动程序通过 Scatter 编译方式,编译到指定的 Section,再通过访
问指定 Section 对应的地址,找到驱动函数入口进行加载。
下面结合一个 Sample 示例代码,讲解驱动加载过程,重点分析静态加载方式下内核态驱动
加载过程。
3.1 实现驱动程序初始化接口
在 HDF 驱动框架中,HdfDriverEntry 对象被用来描述一个驱动实现。
struct HdfDriverEntry {
int32_t moduleVersion;
const char *moduleName;
来源:HarmonyOS 开发者微信号 https://mp.weixin.qq.com/s/crH9YJvG1WwTWrQ-jn__nA
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;
来源:HarmonyOS 开发者微信号 https://mp.weixin.qq.com/s/crH9YJvG1WwTWrQ-jn__nA