OpenHarmony驱动框架HDF中设备管理服务构建过程详解

前言

如下图,开源鸿蒙系统驱动框架HDF在内核中的实现,可以分为向用户层提供设备服务的管理模块(Manager),和实际管理硬件的Host模块。
Manager分为DeviceManageService和 DeviceServiceManage,前者负责提供服务的设备,包括设备驱动匹配、设备驱动装载、设备启动等;后者负责关联设备提供的服务,包括管理Host端提供的设备服务,和接收用户发起的设备服务订阅请求。

图1 开源鸿蒙系统驱动框架软件架构模块图

本文主要关注点在DeviceManageService,叙述其如何启动设备、创建设备服务节点、装载驱动,以及发布服务的过程。

文章内容简介

开源鸿蒙系统驱动框架HDF内核实现部分完全使用C语言实现,也引入了面向对象编程的思想,使用C语言实现了诸如类继承、虚函数、单例类等的概念,使得HDF内核部分包含了大量的对象类型,对象类型又通过的接口形式对外提供服务。

为了向读者展现开源鸿蒙系统驱动框架HDF内核实现蓝图,本文仅仅介绍介绍DevMgr过程中Manager域和Host域内的对象类型与其接口,先奠定读者对HDF内对象类型的基本认识;然后,在下一篇文章中介绍DevMgrService如何启动设备、装载驱动、发布设备服务的整个过程。

本文章节内容如下:

    1. DevMgr域中的对象类型及接口
    1. Host域中的对象类型及接口

1 DevMgr域中的对象类型及接口

1.1 DevmgrService

1.1.1 DevmgrService及接口

DevmgrService是设备管理的总入口,其Hosts域是一个双向链表,hcs设备配置中的所有Host设备被挂载在这个Hosts双向链表上。

DevmgrService内容及其接口定义如下:

struct IDevmgrService {struct HdfObject base;struct HdfDeviceObject object;// 将Host节点链接到DevMgr的hosts列表int (*AttachDeviceHost)(struct IDevmgrService *, uint16_t, struct IDevHostService *);// 将HDF设备节点以Token的形式连接到host的devices列表int (*AttachDevice)(struct IDevmgrService *, const struct HdfDeviceInfo *, struct IHdfDeviceToken *);// 启动DevmgrService服务int (*StartService)(struct IDevmgrService *);int (*PowerStateChange)(struct IDevmgrService *, enum HdfPowerState pEvent);
};struct DevmgrService {struct IDevmgrService super;struct DListHead hosts;struct OsalMutex devMgrMutex;
};

由DevmgrService结构体的内容可知,DevmgrService只管理者host设备节点。 有下面章节可知,Host节点下的所有设备则由Host自己管理。

1.1.2 DevMgrService构建过程

下面DevMgrService构建过程,HDF内核实现部分中使用static局部变量实现了C++中单例类的概念,将DevMgrService作为一个单例类,所有的对象指向同一个实体。

 DevmgrServiceCreate()|  // C++,单例类概念|-> static struct DevmgrService devmgrServiceInstance;|-> DevmgrServiceConstruct(&devmgrServiceInstance)|-> devMgrSvcIf = (struct IDevmgrService *)inst;||-> devMgrSvcIf->AttachDevice =  DevmgrServiceAttachDevice;|-> devMgrSvcIf->AttachDeviceHost = DevmgrServiceAttachDeviceHost;|-> devMgrSvcIf->StartService =  DevmgrServiceStartService;|-> devMgrSvcIf->PowerStateChange = DevmgrServicePowerStateChange;
1.1.3 IDevmgrService接口介绍
(1)StartService:DevmgrServiceStartService()

DevmgrServiceStartService()主要功能是挂载并启动hcs设备配置中的所有host设备节点DevmgrService的hosts链表;然后,启动host节点,间接地启动Host节点下的所有设备(装载设备驱动、发布设备服务等)。

DevmgrServiceStartService()
|-> DevmgrServiceStartDeviceHosts()|-> DriverInstallerGetInstance() //  installer| // (1) 为每一个Hcs配置中的Host设备创建一个DevHostClnt|-> HdfAttributeManagerGetHostList(&hostList);|-> HdfSListIteratorInit(&it, &hostList);|-> hostAttr = HdfSListIteratorNext(&it);||-> hostClnt = DevHostServiceClntNewInstance(|                    hostAttr->hostId,|                    hostAttr->hostName);| // (2) 添加HostClnt到DevMgr的hosts链表|-> DListInsertTail(&hostClnt->node, &inst->hosts);|| // (3) 启动host设备对应的DevHostClnt。|-> hostClnt->hostPid = installer->StartDeviceHost()
(2)AttachDeviceHost:DevmgrServiceAttachDeviceHost()

DevmgrServiceAttachDeviceHost()遍历host节点先的所有设备信息,使用DriverLoader构建设备节点,装载驱动,发布服务,然后将设备链接到Host的devices列表。

DevmgrServiceAttachDeviceHost( struct IDevmgrService *inst, uint16_t hostId,
|                               struct IDevHostService *hostService) 
|
| // DevHostServiceClnt 已经在 StartDeviceHost() 内按照hcs设备配置树中的host节点创建
|-> struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);
|
|-> hostClnt->hostService = hostService;
|   // 获得Host节点下所有的设备节点配置信息
|-> hostClnt->deviceInfos = HdfAttributeManagerGetDeviceList()
|-> hostClnt->devCount = HdfSListCount(hostClnt->deviceInfos);
|
|-> DevHostServiceClntInstallDriver(hostClnt)| // 遍历 Host 节点下的所有设备(设备+驱动),并将它们挂载到host的devices列表|-> HdfSListIteratorInit(&it, hostClnt->deviceInfos);|-> deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&it);|-> devHostSvcIf->AddDevice(devHostSvcIf, deviceInfo);
(3) AttachDevice:DevmgrServiceAttachDevice

被AttachDeviceHost接口实现DevmgrServiceAttachDeviceHost()调用,在完成host下的设备的驱动匹配、装载及设备服务发布后,将HdfDeviceNode以Token的Token 的形式挂接到 DevHostServiceClnt 的 devices 链表。具体过程如下:

DevmgrServiceAttachDevice(struct IDevmgrService *inst, 
|                          const struct HdfDeviceInfo *deviceInfo,
|                          struct IHdfDeviceToken *token)
|
|-> struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, deviceInfo->hostId);
|-> struct DeviceTokenClnt *tokenClnt = 
|                DeviceTokenClntNewInstance(token); // tokenClnt包含指针指向DeviceToken
|                |-> tokenClnt = (struct DeviceTokenClnt *)OsalMemCalloc(sizeof(struct DeviceTokenClnt));
|                |-> DeviceTokenClntConstruct(tokenClnt, tokenIf);
|                    |-> tokenClnt->tokenIf = tokenIf;
|
|-> tokenClnt->deviceInfo = deviceInfo;
|-> DevmgrServiceUpdateStatus(hostClnt, deviceInfo->deviceId, HDF_SERVICE_USABLE);
|-> HdfSListAdd(&hostClnt->devices, &tokenClnt->node);

1.2 DevHostServiceClnt

1.2.1 DevHostServiceClnt对象类型

DevHostServiceClnt为Host域内DevHostService的概念在Manager域的一个表示,hostService成员为IDevHostService的指针,指向被DevHostService包含的IDevHostService对象地址。此处,又借鉴了C++中基类的概念。

struct DevHostServiceClnt {struct DListHead node;               // 链表节点,host设备依次对象挂载在DevMgrService的hosts链表上struct HdfSList devices;             // 链表,挂载所有host下的所有设备(以token的形式)struct HdfSList *deviceInfos;        // 属于Host设备的所有子设备的devInfo信息Map *deviceHashMap;struct IDevHostService *hostService; // 指向Host域的host设备服务的实现uint16_t devCount;                   // 子设备个数uint16_t hostId;                     // 系统内Host设备节点标识,按照加载顺序依次+1;int hostPid;                         // 父Host设备节点标识const char *hostName;                // Host设备名
};
1.2.2 DevHostServiceClnt 构建流程

DevHostServiceClnt的构建过程如下,若该DevHostServiceClnt不存在,则创建一个对象,初始化其hostService和deviceInfos成员,在其下的设备完全启动后,则将该对象链接到DevMgrService的hosts链表。

static int DevmgrServiceAttachDeviceHost(struct IDevmgrService *inst, uint16_t hostId, struct IDevHostService *hostService)
{struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);if (hostClnt == NULL) {HDF_LOGE("failed to attach device host, hostClnt is null");return HDF_FAILURE;}if (hostService == NULL) {HDF_LOGE("failed to attach device host, hostService is null");return HDF_FAILURE;}hostClnt->hostService = hostService;hostClnt->deviceInfos = HdfAttributeManagerGetDeviceList(hostClnt->hostId, hostClnt->hostName);if (hostClnt->deviceInfos == NULL) {HDF_LOGW("failed to get device list ");return HDF_SUCCESS;}hostClnt->devCount = HdfSListCount(hostClnt->deviceInfos);return DevHostServiceClntInstallDriver(hostClnt);
}

2 Host域内对象类型与接口

2.1 DriverInstaller

2.1.1 DriverInstaller 结构体内容描述

DriverInstaller的功能是根据Hcs设备配置文件中的host节点的名称,启动Host节点服务,包括依次创建Host节点下的所有设备、匹配设备驱动、初始化驱动,发布设备服务等。DriverInstaller的内容定义如下:

struct IDriverInstaller {struct HdfObject object;int (*StartDeviceHost)(uint32_t, const char *);
};struct DriverInstaller {struct IDriverInstaller super;
};
2.1.2 DriverInstaller构建过程

DriverInstaller 也作为单例类,使用同一个局部static变量实现。

DriverInstallerCreate()
|-> static struct DriverInstaller driverInstaller;
|
|-> DriverInstallerConstruct(&driverInstaller);|-> driverInstallIf->StartDeviceHost = DriverInstallerStartDeviceHost;
2.1.3 DriverInstaller 接口简介StartDeviceHost : DriverInstallerStartDeviceHost()

DriverInstallerStartDeviceHost()名义上是启动Host节点服务,实则通过DevMgrService在Host域的client(DevmgrServiceClnt)挂载Host节点到DevMgrService的hosts链表,同时还通过DevHostService的AddDevice()接口将host节点其下的所有设备依次匹配驱动、加载驱动、发布设备服务等。

DriverInstallerStartDeviceHost(uint32_t devHostId, const char *devHostName)
| // 创建Host端DevService
|-> struct IDevHostService *hostServiceIf = DevHostServiceNewInstance(devHostId, devHostName);
|
| // hostServiceIf->StartService(hostServiceIf);
|-> DevHostServiceStartService()|-> DevmgrServiceClntAttachDeviceHost()| // 创建Host端的DevMgr的Client(“代理”,更合适), DevmgrServiceClnt即IDevmgrService|-> struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance();|| // 将hostService、devInfo和hostClnt关联,并装载匹配的设备驱动| // devMgrSvcIf->AttachDeviceHost()|-> DevmgrServiceAttachDeviceHost() |-> struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);|-> hostClnt->hostService = hostService;|-> hostClnt->deviceInfos = HdfAttributeManagerGetDeviceList()|-> DevHostServiceClntInstallDriver(hostClnt)

2.2 DriverLoader

2.2.1 DriverLoader 结构体

DriverLoader主要是完成Host节点下的设备的装载,包括匹配驱动(GetDriverEntry())、初始化驱动、发布设备服务等。

struct IDriverLoader {struct HdfObject object;struct HdfDriverEntry *(*GetDriverEntry)(const struct HdfDeviceInfo *deviceInfo);struct HdfDeviceNode *(*LoadNode)(struct IDriverLoader *, const struct HdfDeviceInfo *deviceInfo);void (*UnLoadNode)(struct IDriverLoader *, const struct HdfDeviceInfo *deviceInfo);
};struct HdfDriverLoader {struct IDriverLoader super;
};
2.2.2 DriverLoader 构建

DriverLoader 同样也作为单例类,使用同一个局部static变量实现,比较其不独占任何设备,只是完成设备节点驱动的装载。

HdfDriverLoaderCreate()
|-> static struct HdfDriverLoader driverLoader;
|
|-> HdfDriverLoaderConstruct(&driverLoader);|-> struct IDriverLoader *driverLoaderIf = (struct IDriverLoader *)inst;|-> driverLoaderIf->LoadNode = HdfDriverLoaderLoadNode;|-> driverLoaderIf->UnLoadNode = HdfDriverLoaderUnLoadNode;|-> driverLoaderIf->GetDriverEntry = HdfDriverLoaderGetDriverEntry;
2.2.3 DriverLoader 接口简介
(1) GetDriverEntry : HdfDriverLoaderGetDriverEntry()

从DriverEntry列表中获得指定设备的驱动:

HdfDriverLoaderGetDriverEntry()
|-> static struct HdfDriverEntry *driverEntry = NULL;
|-> static int32_t driverCount = 0;
|
|-> strcmp(deviceInfo->moduleName, driverEntry[i].moduleName) == 0
|-> return &driverEntry[i];
(2) LoadNode : HdfDriverLoaderLoadNode()

简介调用自己的接口GetDriverEntry()完成驱动匹配,然后将设备驱动提供的ioService与HdfDeviceNode的IoService绑定。

HdfDriverLoaderLoadNode(struct IDriverLoader *loader,
|                          const struct HdfDeviceInfo *deviceInfo)
|    // 获得对应设备驱动对象
|-> driverEntry = loader->GetDriverEntry(deviceInfo);
|    // 创建设备节点
|-> devNode = HdfDeviceNodeNewInstance();
|    // 绑定驱动与设备节点
|-> devNode->driverEntry = driverEntry;
|-> devNode->deviceInfo = deviceInfo;
|   // 绑定设备服务与IoService
|-> driverEntry->Bind(&devNode->deviceObject)
|
|-> return devNode;

2.3 DevHostService

Sorry,前面引用了那么多Host,一直未明确其概念。 Host在开源鸿蒙系统中可以理解为平台设备子系统,例如display、Input、Network、Sensor、storage等,在这些子系统中又保护了多种接口的实现。以Display子系统为例,可以是SPI接口的设备,也可以是SDIO接口的设备;而具体到SPI设备,有包括了SPI设备1、2、3等。所以才有了“图1.1.1 DevMgr与host及设备关系图”描述的Host与设备之间的关系。

在host域中,使用DevHostService为host设备节点。

2.3.1 DevHostService 结构体

DevHostService作为Host设备在Host域中的表示,管理着其下的所有设备,每一个具体的设备都以HdfDevice的形式挂载到DevHostService的devices链表,不同于DevHostServiceClnt对设备的管理。

struct IDevHostService {struct HdfObject object;// 添加设备到DevHostService到devices链表int (*AddDevice)(struct IDevHostService *hostService, const struct HdfDeviceInfo *devInfo);int (*DelDevice)(struct IDevHostService *hostService, const struct HdfDeviceInfo *devInfo);// 启动host服务int (*StartService)(struct IDevHostService *hostService);int (*PmNotify)(struct IDevHostService *service, uint32_t powerState);
};struct DevHostService {struct IDevHostService super;uint16_t hostId; 				// host设备在系统中的唯一表示,按照加载顺序,依次+1const char *hostName;struct DListHead devices;		// 链表,挂载着host下所有设备的struct HdfServiceObserver observer;struct HdfSysEventNotifyNode sysEventNotifyNode;
}
2.3.2 DevHostService 构建流程

DevHostService对象的构建比较简单,分配内存,然后初始化,因为对应的是一个个的Host节点,所有也没有单例类的感念。

void DevHostServiceConstruct(struct DevHostService *service)
{struct IDevHostService *hostServiceIf = &service->super;if (hostServiceIf != NULL) {hostServiceIf->AddDevice = DevHostServiceAddDevice;hostServiceIf->DelDevice = DevHostServiceDelDevice;hostServiceIf->StartService = DevHostServiceStartService;hostServiceIf->PmNotify = DevHostServicePmNotify;DListHeadInit(&service->devices);HdfServiceObserverConstruct(&service->observer);}
}
2.3.3 IDevHostService 接口简介
(1)StartService : DevHostServiceStartService()

DevHostServiceStartService()启动HostService,间接调用AddDevice接口,依次加载host下的所有子设备。

DevHostServiceStartService(struct IDevHostService *service)
|-> DevmgrServiceClntAttachDeviceHost()|  //  通过DevMgr在Host端的Client,调用|-> DevmgrServiceAttachDeviceHost()| // 将DevService和deviceInfo与DevHostClnt关联。|-> hostClnt->hostService = hostService;|-> hostClnt->deviceInfos = HdfAttributeManagerGetDeviceList()||-> DevHostServiceClntInstallDriver(hostClnt)|-> devHostSvcIf = (struct IDevHostService *)hostClnt->hostService;|-> HdfSListIteratorInit(&it, hostClnt->deviceInfos);|-> deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&it);|-> devHostSvcIf->AddDevice(devHostSvcIf, deviceInfo);
(2)AddDevice : DevHostServiceAddDevice()

DevHostServiceAddDevice()的功能前面有所带过,主要是根据deviceInfo创建HdfDevice对象、匹配设备驱动、装载设备驱动、DevHostServiceClnt的devcies链表等。

DevHostServiceAddDevice(struct IDevHostService *inst, struct HdfDeviceInfo *deviceInfo)
|-> struct HdfDevice *device = NULL;
|-> struct DevHostService *hostService = CONTAINER_OF(inst, struct DevHostService, super);
|
|-> device = DevHostServiceGetDevice(hostService, deviceInfo->deviceId);
|
|-> devNode = driverLoader->LoadNode(driverLoader, deviceInfo);
|                            |-> HdfDriverLoaderLoadNode()
|                                |-> 
|                                |-> 
|                                |-> driverEntry = loader->GetDriverEntry(deviceInfo);
|                                |                          |-> HdfDriverLoaderGetDriverEntry()
|                                | 
|                                |-> devNode = HdfDeviceNodeNewInstance();
|                                |-> devNode->driverEntry = driverEntry;
|                                |-> devNode->deviceInfo = deviceInfo;
|                                |-> devNode->deviceObject.xx = xx;
|                                | // 绑定HdfDevice与DeviceIoService
|                                | // Device -> service -> Dispatch
|                                |-> driverEntry->Bind(&devNode->deviceObject)
| // 将服务于设备相关联
|-> devNode->hostService = hostService;
| // 挂载DevNode到设备(同一接口设备类)的节点列表(一个设备类中的一个具体设备)
|-> device->super.Attach(&device->super, devNode);

2.4 HdfDevice

2.4.1 HdfDevice 及接口

HdfDevice为Host下的设备在Host域内的表示,内容如下:

struct IHdfDevice {struct HdfObject object;// 挂载HdfDeviceNode到HdfDevice的node链表int (*Attach)(struct IHdfDevice *, struct HdfDeviceNode *);void (*Detach)(struct IHdfDevice *, struct HdfDeviceNode *);
};struct HdfDevice {struct IHdfDevice super;struct DListHead node;struct DListHead devNodes;  // 某接口相同的设备类的具体设备节点,如I2C总线上挂着设备0,设备1uint16_t deviceId;          // 接口相同的设备类,例如UART、I2C等。uint16_t hostId;            // 应用子设备系统类,例如:display、Input、Network、Sensor、storage等。
};
2.4.2 HdfDevice 构建流程

比较简单,分配对象内存空间,然后初始化接口和其中的链表:

void HdfDeviceConstruct(struct HdfDevice *device)
{device->super.Attach = HdfDeviceAttach;DListHeadInit(&device->devNodes);
}struct HdfObject *HdfDeviceCreate()
{struct HdfDevice *device =(struct HdfDevice *)OsalMemCalloc(sizeof(struct HdfDevice));if (device != NULL) {HdfDeviceConstruct(device);}return (struct HdfObject *)device;
}

HdfDevice为Host域内一个设备的表示,一个HdfDevice可以对应多个DeviceNode节点,但是一个DeviceNode节点只对应一个设备驱动。即用户可以将设备驱动程序进行分层,协同完成对设备的支撑。

2.4.3 IHdfDevice 接口 Attach 简介

HdfDeviceAttach()的功能是(1)将设备Node节点挂载到设备的DevNode检点链表上;(2)然后启动节点,即初始化驱动、发布设备服务等。

static int HdfDeviceAttach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode)
{struct HdfDevice *device = (struct HdfDevice *)devInst;struct IDeviceNode *nodeIf = (struct IDeviceNode *)devNode;if (device == NULL || nodeIf == NULL || nodeIf->LaunchNode == NULL) {HDF_LOGE("failed to attach device, input params invalid");return HDF_ERR_INVALID_PARAM;}DListInsertTail(&devNode->entry, &device->devNodes);return nodeIf->LaunchNode(devNode, devInst);
}

2.5 HdfDeviceNode(DeviceNodeExt)

设备节点,对应着一个设备服务节点,与DriverEntry一一对应。

2.5.1 HdfDeviceNode与DeviceNodeExt对象类型定义

现在才是真正与驱动一一对应的设备节点,代表着一个服务设备。

struct IDeviceNode {struct HdfObject object;// 发布设备服务int (*PublishService)(struct HdfDeviceNode *, const char *);// 启动设备节点int (*LaunchNode)(struct HdfDeviceNode *, struct IHdfDevice *);
};struct HdfDeviceNode {struct IDeviceNode super;struct DListHead entry;struct PowerStateToken *powerToken;struct DevHostService *hostService;struct HdfDeviceObject deviceObject;struct IHdfDeviceToken *token;struct HdfDriverEntry *driverEntry;const struct HdfDeviceInfo *deviceInfo;
};struct DeviceNodeExt {struct HdfDeviceNode super;struct HdfIoService *ioService;
};
2.5.2 DeviceNodeExt 构建流程

DeviceNodeExt包含HdfDeviceNode,在C++上表现为继承关系,构建过程如下:

DeviceNodeExtCreate()
|-> struct DeviceNodeExt *instance =
|            (struct DeviceNodeExt *)OsalMemCalloc();
|
|-> DeviceNodeExtConstruct()|-> HdfDeviceNodeConstruct()|    |-> struct IDeviceNode *nodeIf = &devNode->super;|    |-> devNode->token = HdfDeviceTokenNewInstance();|    |-> nodeIf->LaunchNode = HdfDeviceLaunchNode;|    |-> nodeIf->PublishService = HdfDeviceNodePublishPublicService; // 被覆盖||-> nodeIf->PublishService = DeviceNodeExtPublishService;
2.5.3 HdfDeviceNode 接口简介
(1)LaunchNode : HdfDeviceLaunchNode()

HdfDeviceLaunchNode()功能为启动设备节点,初始化设备驱动吗,间接地调用PublishService接口发布设备服务。

HdfDeviceLaunchNode(struct HdfDeviceNode *devNode, struct IHdfDevice *devInst)
|-> device = (struct HdfDevice *)devInst;
|-> driverEntry = devNode->driverEntry;
|
|    // (1)初始化设备驱动
|-> driverEntry->Init(&devNode->deviceObject);
|    // (2)发布设备服务,挂载
|-> HdfDeviceNodePublishService()
|    |  // 将设备节点发布到系统设备节点,并添加服务到DevSvcMgr的服务链表
|    |-> // nodeIf->PublishService()
|    |-> HdfDeviceNodePublishLocalService()
|
|    // (3)挂载HDFDevice到DevMgr的设备链表
|-> deviceToken = devNode->token;
|    // 挂载DevNode(通过DeviceToken)到DevHostServiceClnt的device链表上。
|-> DevmgrServiceClntAttachDevice()|-> DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance();|-> devMgrSvcIf = inst->devMgrSvcIf;| // 将Device挂载DevMgr的设备链表上,以DeviceTokenClnt的形式挂载|-> devMgrSvcIf->AttachDevice(devMgrSvcIf, deviceInfo, deviceToken);
(2)PublishService : HdfDeviceNodePublishPublicService()

发布设备服务即为发布设备节点(DevNode)头部的HdfObject

DeviceNodeExtPublishService(struct HdfDeviceNode *inst, const char *serviceName)
|-> HdfDeviceNodePublishPublicService() // 发布Public服务
|    |-> DevSvcManagerClntAddService()
|        |-> devSvcMgrClnt = DevSvcManagerClntGetInstance();
|        |-> serviceManager = devSvcMgrClnt->devSvcMgrIf; // SvcMgrClnt即为SvcMgr的代理
|        |   // 添加设备服务到设备服务管理器
|        |-> serviceManager->AddService(serviceManager, svcName, service);
|    
|    // 创建设备节点,返回与之关联的VnodeAdapter的ioService域
|-> devNodeExt->ioService = HdfIoServicePublish()
|-> static struct HdfIoDispatcher dispatcher = {
|->        .Dispatch = DeviceNodeExtDispatch
|-> };
|-> devNodeExt->ioService->dispatcher = &dispatcher;

2.6 HdfDriverEntry

HdfDriverEntry即设备驱动对象,对应一个设备节点。

struct HdfDriverEntry {// Driver versionint32_t moduleVersion;// Driver module name, to match the driver information in .hcs fileconst char *moduleName;//to bind DriverIoService to HdfDevServiceint32_t (*Bind)(struct HdfDeviceObject *deviceObject); // // Initializes the driver.int32_t (*Init)(struct HdfDeviceObject *deviceObject);// Releases driver resourcesvoid (*Release)(struct HdfDeviceObject *deviceObject);
};

3 总结

至此,本文已经介绍了DevMgrService构建过程中遇到的绝大部分对象类型,其目的是先为读者勾画出每个对象类型的功能,使读者在阅读源码的初始阶段,可以在不深入调入流程的情况下,对DevMgrService的构建流程有个大概的印象,而不是被代码牵引,一层层向下深入,最后被众多的对象所淹没。

以此铺垫,在下一篇文章中,将介绍DevMgrService的构建过程,众多的对象类型,诸如DevHostServiceClnt、DevHostService、HdfDevice、HdfDeviceNode、HdfDriverEntry以及HdfDeviceToken等,将关联成一张负责的关系网。


为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:https://qr21.cn/FV7h05

入门必看:https://qr21.cn/FV7h05

  1. 应用开发导读(ArkTS)
  2. ……

HarmonyOS 概念:https://qr21.cn/FV7h05

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. 构建第一个JS应用
  4. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

总结

鸿蒙系统开发作为当下的一个风口,对于有志于投身技术领域的小白来说是一个难得的机遇。通过深入了解鸿蒙系统的技术优势和市场前景,你将能够做出明智的选择。记住,站在风口上,猪都能飞起来,而掌握鸿蒙开发技能,或许就是你起飞的翅膀。现在就开始行动吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/696749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1.WEB渗透测试-前置基础知识-ip地址

ip地址: ip地址指的是互联网协议地址,是IP协议提供的一种统一的地址格式,以每一台联网的主机都有一个对应的ip地址,ip地址也可以理解为分配给用户上网使用的网际协议的设备的数字标签。通俗的来说就是你打电话时候的每个人都有自己…

在Mac上搭建MongoDB环境

最近工作中需要装MongoDB环境,搭建过程中遇到了一些问题,在这里记录一下安装MongoDB环境的方法以及问题的解决方法。有两种安装MongoDB的方法:brew安装和手动安装。 目录 使用Homebrew安装MongoDB 手动安装MongoDB(不使用Homebr…

vue--两种定时任务cron表达式组件比较选择

背景&#xff1a; 使用vue页面中cron表达式的组件&#xff0c;实现定时任务参数配置。 方案1 vue-cron 安装插件 npm install vue-cron --save 全局引入&#xff0c;修改main.js import Vue from vue import VueCron from vue-cron Vue.use(VueCron);页面配置 html<el-…

Java入门-可重入锁

可重入锁 什么是可重入锁? 当线程获取某个锁后&#xff0c;还可以继续获取它&#xff0c;可以递归调用&#xff0c;而不会发生死锁&#xff1b; 可重入锁案例 程序可重入加锁 A.class,没有发生死锁。 sychronized锁 package com.wnhz.lock.reentrant;public class Sychroniz…

linux系统内核升级

1.查看旧版本内核 2.导入密钥 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org 3.安装yum源 rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm4.启用elrepo-kernel仓库并安装最新内核版本 yum --enablerepoelrepo-kernel install …

一文弄明白KeyedProcessFunction函数

引言 KeyedProcessFunction是Flink用于处理KeyedStream的数据集合&#xff0c;它比ProcessFunction拥有更多特性&#xff0c;例如状态处理和定时器功能等。接下来就一起来了解下这个函数吧 正文 了解一个函数怎么用最权威的地方就是 官方文档 以及注解&#xff0c;KeyedProc…

c++实现栈和队列类

c实现栈和队列类 栈(Stack)Stack示意图Stack.cpp 队列(queue)queue 示意图queue.cpp 栈(Stack) Stack示意图 Stack.cpp #pragma once #include "ListStu.cpp"template<typename T> class Stack { public: /* * void push(T& tDate)* 参数一 &#xff1a;…

记录解决uniapp使用uview-plus在vue3+vite+ts项目中打包后样式不能显示问题

一、背景 从 vue2uview1 升级到 vue3vitetsuview-plus ,uview组件样式打包后不显示&#xff0c;升级前uview 组件是可以正常显示&#xff0c;升级后本地运行是可以正常显示&#xff0c;但是打包发布成H5后uview的组件无法正常显示&#xff0c;其他uniapp自己的组件可以正常显示…

Vue 中 onclick和@click区别

文章目录 一、直接上结论二、验证代码&#xff0c;可直接运行三、点击结果 一、直接上结论 onclick 只能触发 js的原生方法&#xff0c;不能触发vue的封装方法click 只能触发vue的封装方法&#xff0c;不能触发js的原生方法 二、验证代码&#xff0c;可直接运行 <!DOCTYP…

Vue3 + Ts (使用lodash)

安装 npm i --save lodash使用 import _ from lodash⚠️报警告&#xff1a;&#xff01;&#xff01;&#xff01; 此时还需要安装ts声明文件库 npm install types/lodash -D安装之后重启Vscode还是会提示上面的警告&#xff0c;此时还需在tsconfig.ts里面配置 {"c…

快速将excel/word表格转换为web页面(html)的方法

前言 在进行开发企业信息化建设的过程&#xff0c;应该有很多这样的场景&#xff0c;就是将现有的电子表格记录的方式转换为在数据系统中进行网页上报。也就是需要根据当前一直使用的表格制作一个上传这个表格信息的网页&#xff0c;如果要减少系统的使用学习成本&#xff0c;…

leetcode:78.子集

1.树形结构&#xff1a;往后依次取该数字往后的数字&#xff08;前面的不要取&#xff0c;否则子集会重复&#xff09;&#xff1b;每一层递归的结果都要放入结果集&#xff0c;而并非只放叶子节点。 代码实现&#xff1a; #达到了叶子节点&#xff08;终止条件&#xff09; …

抖音百科词条创建在哪里?

抖音百科就是头条百科&#xff0c;头条百科是一个在线百科全书平台&#xff0c;用户可以在上面创建、编辑和浏览各种百科词条。头条百科词条可以被抖音抓取到&#xff0c;从而获得更多流量和曝光&#xff0c;所以当你创建一个抖音百科词条的时候&#xff0c;就能更加提高自身的…

人工智能_CPU安装运行ChatGLM大模型_ChatGlm-6B_启动命令行对话_安装API调用接口_005---人工智能工作笔记0100

然后我们再进入 /data/module/ChatGLM-6B-main文件夹 然后我们去启动,命令行工具 python3 cli_demo.py 可以看到也是可以用了. 正常可以用了. 然后主要来看,如何使用api来调用呢,这样才可以,做自己的界面 可以看到就非常简单了只需要: 走到 /data/module/

即时设计和sketch对比

在设计领域&#xff0c;有很多易于使用的设计软件&#xff0c;每个软件都有自己的特点&#xff0c;但在使用中也会有一些限制。例如&#xff0c;传统的Sketch。Sketch是一款古老的UI设计软件。自2010年推出以来&#xff0c;已有10多年的历史&#xff0c;但它始终仅限于MAC。到目…

【JS逆向学习】同花顺(q.10jqka)补环境

逆向目标 目标网址&#xff1a;https://q.10jqka.com.cn/ 目标接口&#xff1a; https://q.10jqka.com.cn/index/index/board/all/field/zdf/order/desc/page/3/ajax/1/ 目标参数&#xff1a;cookie 逆向过程 老规矩&#xff0c;先分析网络请求&#xff0c;发现是 cookie 加…

matlab代码--基于matlabLDPC-和积译码系统

LDPC编码 一个码长为n、信息位个数为k的线性分组码&#xff08;n,k&#xff09;可以由一个生成矩阵 来定义&#xff0c;信息序列 通过G被映射到码字XS.G。线性分组码也可以由一个校验矩阵 来描述。所以码字均满足 。校验矩阵的每一行表示一个校验约束 &#xff0c;其中所有的非…

一文吃透计算机网络面试八股文

面试网站&#xff1a;topjavaer.cn 目录&#xff1a; 网络分层结构三次握手两次握手可以吗&#xff1f;四次挥手第四次挥手为什么要等待2MSL&#xff1f;为什么是四次挥手&#xff1f;TCP有哪些特点&#xff1f;说说TCP报文首部有哪些字段&#xff0c;其作用又分别是什么&…

电阻知识详解

基本介绍 电阻阻碍电流流动&#xff1a;只要有电流流过电阻&#xff0c;就会产生功率损耗 基本单位&#xff1a;欧姆&#xff0c;Ω 换算单位&#xff1a;微欧&#xff08;uΩ&#xff09;、毫欧&#xff08;mΩ&#xff09;、千欧&#xff08;kΩ&#xff09;、兆欧&#x…

字典树相关例题题解

一.P2580 于是他错误的点名开始了 这道题也类似于模版题&#xff0c;只要我们熟悉插入和查找的过程&#xff0c;一样可以解决&#xff0c;这里只要注意一下第一次出现和其它次出现所输出是不一样的&#xff0c;这里我们只要在查找函数中返回不同的值&#xff0c;这样就可以解决…