鸿蒙系统实战短视频App 从0到1掌握HarmonyOS之初探HarmonyOS

133 阅读5分钟

//xia仔k:鸿蒙系统实战短视频App 从0到1掌握HarmonyOS

开发指导

场景引见

关于驱动的开发我们主要目的是完成驱动代码的编写,但是驱动开发过程中需求效劳管理、音讯机制管理,才干使驱动在代码编译过程中停止加载。以下开发步骤中引见了驱动开发、驱动音讯机制管理开发、驱动效劳管理开发的步骤。

驱动开发实例

基于HDF框架的驱动开发主要分为三个局部:驱动完成、驱动编译脚本编写和驱动配置。细致开发流程如下所示:

驱动完成

驱动完成包含驱动业务代码完成和驱动入口注册,详细写法如下:

驱动业务代码

#include "hdf_device_desc.h"          // HDF框架对驱动开发相关才能接口的头文件
#include "hdf_log.h"                  // HDF框架提供的日志接口头文件
#define HDF_LOG_TAG sample_driver     // 打印日志所包含的标签,假如不定义则用默许定义的HDF_TAG标签。
// 将驱动对外提供的效劳才能接口绑定到HDF框架。
int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGD("Sample driver bind success");
    return HDF_SUCCESS;
}
// 驱动本身业务初始化的接口
int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGD("Sample driver Init success");
    return HDF_SUCCESS;
}
// 驱动资源释放的接口
void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGD("Sample driver release success");
    return;
}

驱动入口注册到HDF框架

// 定义驱动入口的对象,必需为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量。
struct HdfDriverEntry g_sampleDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "sample_driver",
    .Bind = HdfSampleDriverBind,
    .Init = HdfSampleDriverInit,
    .Release = HdfSampleDriverRelease,
};
// 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动;当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
HDF_INIT(g_sampleDriverEntry);

驱动编译脚本编写

LiteOS

触及Makefile和BUILD.gn修正:

Makefile局部:

驱动代码的编译必需要运用HDF框架提供的Makefile模板停止编译。

include $(LITEOSTOPDIR)/../../drivers/hdf_core/adapter/khdf/liteos/lite.mk # 【必需】导入hdf预定义内容
MODULE_NAME :=        #生成的结果文件
LOCAL_INCLUDE :=      #本驱动的头文件目录
LOCAL_SRCS :=         #本驱动的源代码文件
LOCAL_CFLAGS :=      #自定义的编译选项
include $(HDF_DRIVER) #导入Makefile模板完成编译

编译结果文件链接到内核镜像,添加到drivers/hdf_core/adapter/khdf/liteos目录下的hdf_lite.mk里面,示例如下:

LITEOS_BASELIB +=  -lxxx  #链接生成的静态库
LIB_SUBDIRS    +=         #驱动代码Makefile的目录

BUILD.gn局部:

添加模块BUILD.gn,可参考如下示例:

import("//build/lite/config/component/lite_component.gni")
import("//drivers/hdf_core/adapter/khdf/liteos/hdf.gni")
module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
module_name = "xxx"
hdf_driver(module_name) {
    sources = [
        "xxx/xxx/xxx.c",           #模块要编译的源码文件
    ]
    public_configs = [ ":public" ] #运用依赖的头文件配置
}
config("public") {                 #定义依赖的头文件配置
    include_dirs = [
        "xxx/xxx/xxx",             #依赖的头文件目录
    ]
}

把新增模块的BUILD.gn所在的目录添加到/drivers/hdf_core/adapter/khdf/liteos/BUILD.gn里面:

group("liteos") {
    public_deps = [ ":$module_name" ]
    deps = [
        "xxx/xxx",#新增模块BUILD.gn所在的目录,/drivers/hdf_core/adapter/khdf/liteos
    ]
}

Linux

假如需求定义模块控制宏,需求在模块目录xxx里面添加Kconfig文件,并把Kconfig文件途径添加到drivers/hdf_core/adapter/khdf/linux/Kconfig里面:

source "drivers/hdf/khdf/xxx/Kconfig" #目录为hdf模块软链接到kernel里面的目录

添加模块目录到drivers/hdf_core/adapter/khdf/linux/Makefile:
obj-$(CONFIG_DRIVERS_HDF) += xxx/
在模块目录xxx里面添加Makefile文件,在Makefile文件里面添加模块代码编译规则:
obj-y += xxx.o
驱动配置

HDF运用HCS作为配置描绘源码,HCS细致引见配置管理。

驱动配置包含两局部,HDF框架定义的驱动设备描绘和驱动的私有配置信息,详细写法如下:

驱动设备描绘(必选)

HDF框架加载驱动所需求的信息来源于HDF框架定义的驱动设备描绘,因而基于HDF框架开发的驱动必需要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描绘。驱动的设备描绘填写如下所示:

root {
    device_info {
        match_attr = "hdf_manager";
        template host {       // host模板,继承该模板的节点(如下sample_host)假如运用模板中的默许值,则节点字段能够缺省。
            hostName = "";
            priority = 100;
            uid = "";         // 用户态进程uid,缺省为空,会被配置为hostName的定义值,即普通用户。
            gid = "";         // 用户态进程gid,缺省为空,会被配置为hostName的定义值,即普通用户组。
            caps = [""];      // 用户态进程Linux capabilities配置,缺省为空,需求业务模块依照业务需求停止配置。
            template device {
                template deviceNode {
                    policy = 0;
                    priority = 100;
                    preload = 0;
                    permission = 0664;
                    moduleName = "";
                    serviceName = "";
                    deviceMatchAttr = "";
                }
            }
        }
        sample_host :: host{
            hostName = "host0";    // host称号,host节点是用来寄存某一类驱动的容器。
            priority = 100;        // host启动优先级(0-200),值越大优先级越低,倡议默许配100,优先级相同则不保证host的加载次第。
            caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"];   // 用户态进程Linux capabilities配置。
            device_sample :: device {        // sample设备节点
                device0 :: deviceNode {      // sample驱动的DeviceNode节点
                    policy = 1;              // policy字段是驱动效劳发布的战略,在驱动效劳管理章节有细致引见。
                    priority = 100;          // 驱动启动优先级(0-200),值越大优先级越低,倡议默许配100,优先级相同则不保证device的加载次第。
                    preload = 0;             // 驱动按需加载字段。
                    permission = 0664;       // 驱动创立设备节点权限
                    moduleName = "sample_driver";      // 驱动称号,该字段的值必需和驱动入口构造的moduleName值分歧。
                    serviceName = "sample_service";    // 驱动对外发布效劳的称号,必需独一。
                    deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必需和驱动私有数据配置表中的match_attr值相等。
                }
            }
        }
    }
}

阐明:

uid、gid、caps等配置项是用户态驱动的启动配置,内核态不用配置。

依据进程权限最小化设计准绳,业务模块uid、gid不用配置,如上面的sample_host,运用普通用户权限,即uid和gid被定义为hostName的定义值。

假如普通用户权限不能满足业务请求,需求把uid、gid定义为system或者root权限时,请找平安专家停止评审。

进程的uid在文件base/startup/init/services/etc/passwd中配置,进程的gid在文件base/startup/init/services/etc/group中配置,进程uid和gid配置参考:系统效劳用户组添加办法。

caps值:格式为caps = ["xxx"],假如要配置CAP_DAC_OVERRIDE,此处需求填写caps = ["DAC_OVERRIDE"],不能填写为caps = ["CAP_DAC_OVERRIDE"]。

preload:驱动按需加载字段。

驱动私有配置信息(可选)

假如驱动有私有配置,则能够添加一个驱动的配置文件,用来填写一些驱动的默许配置信息。HDF框架在加载驱动的时分,会将对应的配置信息获取并保管在HdfDeviceObject中的property里面,驱动的配置信息示例如下:

root {
    SampleDriverConfig {
        sample_version = 1;
        sample_bus = "I2C_0";
        match_attr = "sample_config";   // 该字段的值必需和device_info.hcs中的deviceMatchAttr值分歧
    }
}

配置信息定义之后,需求将该配置文件添加到板级配置入口文件hdf.hcs,示例如下:

<button type="button" class="btn btn-dark rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="#include "device_info/device_info.hcs" #include "sample/sample_config.hcs"" aria-label="复制" data-bs-original-title="复制">

#include "device_info/device_info.hcs"
#include "sample/sample_config.hcs"