在2月25日刚刚圆满闭幕的首届开放原子开源基金会OpenHarmony技术峰会(2023)生态与互联分论坛上,润和软件旗下子公司江苏润开鸿数字科技有限公司(简称:润开鸿)资深软件开发工程师梁开祝发表了题为《OpenHarmony的驱动框架原理和实践》的主题演讲,从实践角度重点讲解了OpenHarmony驱动框架的具体实现细节和“一次开发,多系统部署”的驱动开发实践,帮助OpenHarmony设备驱动开发者深入理解驱动框架工作流程和工作细节。
技术背景
OpenHarmony引入全新驱动开发理念和框架
OpenHarmony是一个面向万物互联/万物智联大场景的分布式操作系统,它面对的是硬件性能和功能需求千差万别的设备,比如智能手环与手机之间的硬件差异。为了统一适配能力差别巨大的设备,OpenHarmony设计了一个多内核的架构,能力弱的设备选用简单的内核(如LiteOS)、能力强的设备选用复杂的内核(如Linux),这意味着生态圈中的硬件产品在系统内核层面上就存在巨大的差异。然而这些产品很有可能会用到相近甚至相同的外围硬件,比如,家里的智能门禁系统、智能电视、平板电脑、手机上所使用的摄像头模组都可能是同一个型号或同系列的,而在设备端运行不同内核的操作系统,就需要为不同内核开发各自的驱动程序,这会造成驱动程序的复用性、可移植性、可维护性较差,不利于产品开发和维护,也不利于硬件生态圈的成长。
作为一个全新的操作系统,OpenHarmony必须要开发一套更优秀的驱动开发框架,帮助开发者、企业更便捷地开发和管理硬件设备的驱动程序,助力打造自己的硬件生态。OpenHarmony的驱动框架,采用C语言面向对象编程模型构建,通过平台解耦、内核解耦,来达到兼容不同内核,统一平台底座的目的,从而帮助开发者实现驱动一次开发,多系统部署的效果。
OpenHarmony的内核子系统(多内核)与驱动子系统(统一的驱动框架)是松耦合的关系,仅通过一个OSAL(Operating System Abstraction Layer,操作系统抽象层)进行交互。OSAL只为驱动框架提供内核部分关键能力的抽象接口,而隐藏了接口在不同内核中的实现细节。驱动框架通过OSAL来适配不同的内核,而具体的设备则完全基于驱动框架提供的能力来实现驱动程序并通过HDI(Hardware Driver Interface,硬件驱动接口)对上层提供驱动服务,设备驱动完全不需要知道(也不会知道)自己运行在什么样的内核之上。
技术干货
OpenHarmony中的驱动框架实现详解
代码结构
图为OpenHarmony的驱动框架以及与驱动开发相关代码部署。驱动框架主要在//drivers/hdf_core/目录下实现。
l framework/目录是C语言实现的驱动框架核心源代码(包括驱动框架、配置管理、配置解析、驱动通用模型、硬件通用平台能力接口等),
注意点:这里的部分代码是内核态驱动框架与用户态驱动框架共用的,需要大家在阅读代码时区分清楚;
l adapter/目录下是驱动框架适配不同内核的适配代码和编译脚本,也包括用户态驱动框架适配不同系统类型(轻量系统和标准系统)的适配代码和编译脚本。
l //drivers/peripheral/目录下是部署在OpenHarmony用户空间的各种外围设备驱动相关的HDI、HAL、驱动模型及测试用例等的实现代码和编译配置。
l //drivers/interface/目录下是用于管理各驱动模块的HDI接口定义,这些接口定义使用IDL语言描述并以.idl文件形式保存。
l 其他与驱动开发相关的代码目录还包括//device/目录和//vendor/目录下的相关部分目录,它们是具体的芯片方案、产品方案、产品定义、产品配置等相关信息和适配代码的汇总,为设备驱动的实现提供一定的支持。
编译与链接
驱动框架适配不同内核的编译配置,在代码结构的//drivers/hdf_core/adapter/目录下,主要还是通过对应的BUILD.gn和Makefile文件将相关的源代码进行串联和依赖,以完成驱动框架整体的编译与链接。
对于不同的内核,则在对应内核的编译脚本中加入编译驱动框架的入口和链接描述。
图中代码示例是在LiteOS_A内核的编译脚本中include驱动框架的编译入口,同时也在链接脚本中加入一个hdf.driver的只读数据段,用以描述驱动框架专用的数据结构。
图中代码示例是在Linux内核的编译脚本中,将驱动框架的关键代码以patch的形式打入Linux源代码中(实际仍是代码目录的软链接形式加入Linux内核中),同时也在链接脚本vmlinux.lds.S中加入一个hdf.driver的只读数据段,用以描述驱动框架专用的数据结构。
当编译到OpenHarmony内核时,编译工具链通过上述脚本的描述一并将驱动框架编译成中间文件,然后链接和打包到内核镜像中使用。
内核态驱动框架及用户态驱动框架启动流程
内核态驱动框架的启动流程
如图所示,部署在内核态的驱动框架作为一个相对独立的部分,要么因为内核(LiteOS_A内核)的其他模块的直接调用而启动,要么作为内核(Linux内核)的一个模块(module)而自动加载和启动。在进入驱动框架的启动入口之后,驱动框架就会进入一个与内核无关的工作流程中(与内核相关部分会通过OSAL接口对接到内核提供的功能)。
用户态驱动框架的启动流程
如图所示,部署在用户态的驱动框架则分为若干个独立的服务进程,在系统启动到用户态阶段时,由Init进程根据启动配置文件的描述逐一拉起,各进程之间通过IPC进行交互并逐步建立起各自的数据结构关系。
以上两张示意图均为以功能模块划分的启动流程概略图,梁开祝老师在阅读理解OpenHarmony驱动框架的代码时,以API为粒度整理了一份详细的启动流程图,以及在驱动框架启动过程中一步步建立起来的数据结构关系图,感兴趣的读者可到资源仓库下载、阅读。
用户态与内核态的交互
内核态的驱动框架与用户态的驱动框架是各自独立的两部分,内核态驱动框架直接管理具体硬件设备的驱动,并以服务的形式向用户态提供服务接口,而用户态驱动框架则通过HDI接口使用内核态驱动框架提供的驱动服务。
HDI接口使用IO Service和IO Dispatcher机制为驱动框架提供进行统一的交互接口,其实现主要有两种形式:
l 当驱动以内核态组件形式部署时,客户端程序需要通过系统调用(system call)方式访问驱动程序。驱动接口通过IO Service请求将消息通过系统调用陷入内核,并将消息分发到IO Dispatcher进行处理。
l 当驱动以用户态服务形式部署时,客户端进程需要通过IPC方式访问驱动服务进程,IO Service完成IPC 通信的客户端消息请求封装,IO Dispatcher完成驱动服务端消息请求封装,客户端消息通过IPC送达服务端再分发给IO Dispatcher处理。
注意点:该交互过程涉及比较复杂的数据处理流程,需要结合代码进行深入理解。
通用的驱动示例程序
以一个通用的驱动示例程序来简单验证基于OpenHarmony驱动框架的设备驱动开发基本要点。
本驱动示例程序,包含了驱动框架的一些基本要素,如上层的应用程序、内核的驱动程序、硬件的驱动配置信息、适配不同内核和不同类型系统的编译脚本等。小伙伴们可以跟着里面的README文档的操作说明,从简单到复杂一步步去验证前文提到的驱动框架知识要点,也可以非常方便地将这个示例程序移植到不同的开发板上进行验证,以此体验OpenHarmony驱动框架“一次开发,多系统部署”的好处。
“以技术赋能开源共建,持续发挥生态引领作用”。润和软件将深入贯彻“2+N”行业战略(深耕金融、能源“2”大行业,广泛赋能智慧城市、医疗、教育、工业等“N”个行业),围绕行业场景落地不断夯实软硬件底座,推动应用创新,助力体验提升;吸引更多企业及个人开发者融入生态、参与共建,持续为OpenHarmony繁荣发展贡献力量。
全部0条评论
快来发表一下你的评论吧 !