OpenHarmony驱动框架HDF中设备管理服务构建过程详解(二) 原创 精华

深开鸿
发布于 2022-5-20 12:46
浏览
5收藏

作者: 侯旗

在上篇文章《 OpenHarmony驱动框架HDF中设备管理服务构建过程详解(一)》中,介绍了设备管理服务涉及的对象类型及其相应的接口,也初步展示了设备管理服务中的对象类型关系网。如下图所示

OpenHarmony驱动框架HDF中设备管理服务构建过程详解(二)-鸿蒙开发者社区

在本篇文章中,我们开始叙述这张网的构建过程,按照上图中标识的数字,将本篇文章分为4个章节:

  • 1. 创建DevHostServiceClnt
  • 2. 创建DevHostService
  • 3. 创建HdfDevice
  • 4. 创建HdfDeviceNode

在介绍上述对象类型实体的过程中,也会介绍这些对象是如何进行关联的。

1 DevmgrService 构建DevHostServiceClnt

有上图可知,DevMgrService 并不是管理所有的设备,而只是管理host设备,而且 DevMgrService 管理的不是host设备,而是host设备服务的客户端(DevHostServiceClnt),所以DevMgrService管理的是DevHostServiceClnt。

1.1 DevMgrService的启动过程

DevMgrService的启动以DeviceManagerInit()为起点,以late_initcall()为入口点,被静态编译进内核,在内核启动后期启动,其启动过程如下:

late_initcall(DeviceManagerInit);
|-> DeviceManagerInit()
    |-> DeviceManagerStart()
        | // (1)创建DevMgr对象
        |-> instance = DevmgrServiceGetInstance();
        | // (2)发布DevMgr,"/dev/hdf/"+"dev_mgr"
        |-> ioService = HdfIoServicePublish(DEV_MGR_NODE, DEV_MGR_NODE_PERM);
        | // (3)启动DevMgr服务
        |-> instance->StartService(instance);

如上,在函数 DeviceManagerStart() 内,调用HdfIoServicePublish() 将DevMgrService发布为一个设备服务节点“/dev/hdf/dev_mgr”,是为了能像控制器一般设备服务一样控制DevMgrService服务。

在最后,调用 DevMgrService的接口 StartService,即 DevmgrServiceStartService() 启动设备管理服务主体,其实就是为一个个host设备创建 DevHostServiceClnt ,并启动对应的 Host 设备在Host域内的DevHostService。

1.2 DevmgrService 构建host服务客户端

所有Host设备源于hcs设备配置树,DevMgrService 的 StartService 接口实现 DevmgrServiceStartService()调用HcsGetRootNode()依据hcs设备配置树构建其在内存内的树形结构链表g_hcsTreeRoot,然后GetHdfManagerNode()从该链表内获取根节点"hdf_manager"。然后依次创建Host设备服务在Manager域的Client节点——DevHostServiceClnt,并将该client节点添加到DevMgrService的hosts链表上。
具体过程如下:

DeviceManagerInit()
|-> DeviceManagerStart()
    | // IDevmgrService :: StartService();
    |-> DevmgrServiceStartService()
        |   // 获得DriverInstaller单例类对象指针
        |-> installer = DriverInstallerGetInstance();
        |
        |   // (1.1)初始化host设备链表hostList
        |-> HdfAttributeManagerGetHostList(&hostList)
        |   |   // 由hcs设备配置树构建内存内hcs树,并获得根节点"hdf_manager"
        |   |-> hdfManagerNode = GetHdfManagerNode(HcsGetRootNode());
        |   |-> hostNode = hdfManagerNode->child;
        |   |-> while (hostNode != NULL) {
        |   |->     struct HdfHostInfo *hostInfo = HdfHostInfoNewInstance();
        |   |->     GetHostInfo(hostNode, hostInfo);
        |   |->     hostInfo->hostId = hostId;
        |   |->     HdfSListAddOrder(hostList, &hostInfo->node, HdfHostListCompare)
        |   |->     hostId++;
        |   |->     hostNode = hostNode->sibling;
        |   |-> }
        |
        |   //// (1.2)初始化递归链表it
        |-> HdfSListIteratorInit(&it, &hostList);
        |
        |-> while (HdfSListIteratorHasNext(&it)) {
        |->     hostAttr = (struct HdfHostInfo *)HdfSListIteratorNext(&it);
        |       // (2.1)创建host服务客户端(DevHostServiceClnt)
        |->     hostClnt = DevHostServiceClntNewInstance(hostAttr->hostId, hostAttr->hostName);
        |                  |-> struct DevHostServiceClnt *hostClnt =
        |                           struct DevHostServiceClnt *)OsalMemCalloc(sizeof(struct DevHostServiceClnt));
        |       // (2.2)添加DevHostServiceClnt对象到DevMgrService的hosts链表
        |->     DListInsertTail(&hostClnt->node, &inst->hosts);
        |       // (3)启动Host设备服务(进一步启动host设备下的所有设备:装载各设备驱动、发布设备服务等)
        |->     hostClnt->hostPid = installer->StartDeviceHost(hostAttr->hostId, hostAttr->hostName)
        |-> }

经过如上的DevMgrService的启动流程,则创建DevMgrService的Hosts链表内的Host服务,如下图所示:

OpenHarmony驱动框架HDF中设备管理服务构建过程详解(二)-鸿蒙开发者社区

2 DriverInstaller 构建Host设备服务DevHostService

在本节中,利用DriverInstaller的StartDeviceHost接口,在启动Host设备服务的过程中创建 DevHostService。为了将Host域中的DevHostService与Manager域中的DevHostServiceClnt 相关联,调用了DevmgrService在Host域client端DevmgrServiceClnt。DevmgrServiceClnt实际上就是DevHostServiceClnt“本尊”。 调用IDevmgrService的AttachDeviceHost接口实现DevmgrServiceAttachDeviceHost(), 将Host域内的DevHostService对象Attach到Manager域的DevHostServiceClnt。

创建DevHostService,并将DevHostService与DevHostServiceClnt关联的过程如下:

// IDriverInstaller:: StartDeviceHost
DriverInstallerStartDeviceHost(uint32_t devHostId, const char *devHostName)
|   // IDevHostService:: StartService
|-> DevHostServiceStartService()
    | 
    |-> DevmgrServiceClntAttachDeviceHost()
        |  // 虽名称为client,实际却是“本尊”
        |-> struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance();
        |   // IDevmgrService:: AttachDeviceHost
        |-> DevmgrServiceAttachDeviceHost()
        |
        |-> hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);
        |-> hostClnt->hostService = hostService;
        |-> hostClnt->deviceInfos = HdfAttributeManagerGetDeviceList(hostClnt->hostId, hostClnt->hostName);
        |-> hostClnt->devCount = HdfSListCount(hostClnt->deviceInfos);
        |  // 名为“InstallDriver”,实际上却是依次启动Host节点下的所有设备服务
        |-> DevHostServiceClntInstallDriver()

DevHostService与DevHostServiceClnt关联关系如下图:

OpenHarmony驱动框架HDF中设备管理服务构建过程详解(二)-鸿蒙开发者社区

3 DevHostService 构建HdfDevice

3.1 DevMgrService依次启动Host节点下的所有设备

接上文,DriverInstaller在Host域反向调用Manager域中的DevMgrService的AttachDeviceHost接口将HostService与其在Manager域中的Client相关联后,便开始装载host设备的驱动,实际上是装载Host节点下所有设备的设备驱动,并初始化驱动,最后发布设备服务。

// IDriverInstaller:: StartDeviceHost
DevmgrServiceAttachDeviceHost()
|-> DevHostServiceClntInstallDriver()
    |-> devHostSvcIf = (struct IDevHostService *)hostClnt->hostService;
    |
    |-> HdfSListIteratorInit(&it, hostClnt->deviceInfos);
    |-> while (HdfSListIteratorHasNext(&it)) {
    |->     deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&it);
    |->     devHostSvcIf->AddDevice(devHostSvcIf, deviceInfo);
    |->  }

3.2 创建HdfDevice对象并将其挂载到DevHostService的devices链表

DevHostService的AddDevice接口负责为Host节下的每个设备创建一个HdfDevice类型对象,并且把新创建的对象挂载到DevHostService的Devices链表中,过程如下:

// IDevHostService:: AddDevice
DevHostServiceAddDevice()
 |-> device = DevHostServiceGetDevice(hostService, deviceInfo->deviceId);
			  | // 创建HdfDevice对象
			  |-> struct HdfDevice *device = HdfDeviceNewInstance();
			  |-> device->hostId = inst->hostId;
			  |-> device->deviceId = deviceId;
			  | // 将HdfDevice对象挂载到DevHostService的devices链表
			  |-> DListInsertHead(&device->node, &inst->devices);

将HdfDevice挂载到DevHostService的Devices链表,构成如下的DevHostService与HdfDevice的关系图:

OpenHarmony驱动框架HDF中设备管理服务构建过程详解(二)-鸿蒙开发者社区

为按照文章开始的对象类型关系图叙述对象类型实体的创建过程,上面只描述了HdfDevice的创建过程。实际上,除此之外,DevHostServiceAddDevice()还负责设备驱动的匹配、加载、初始化,以及发布设备服务等,这些在下一章节叙述。

4 DriverLoader 构建设备节点HdfDeviceNode

接上节,继续叙述DevHostServiceAddDevice()其余功能,包含创建HdfDeviceNode、匹配并装载设备驱动、发布服务等。

4.1 DriverLoader 创建设备节点HdfDeviceNode

HdfDeviceNode与设备驱动一一对应,但是一个HdfDeviceNode可能对应着多个设备,对应关系与Hcs设备配置树中的配置有关。在DriverLoader的LoadNode接口的实现函数HdfDriverLoaderLoadNode(),按照设备信息中的moduleName依次匹配系统设备驱动列表中的驱动项,若匹配成功,则将设备驱动的入口地址关联到HdfDeviceNode的driverEntr指针,而且会将设备驱动提供的IoService服务与设备服务相关联(driverEntry->Bind())。

// IDevHostService:: AddDevice();
DevHostServiceAddDevice()
|-> device = DevHostServiceGetDevice(hostService, deviceInfo->deviceId);
|
| // DriverLoader:: LoadNode
|-> devNode = HdfDriverLoaderLoadNode(struct IDriverLoader *loader, const struct HdfDeviceInfo *deviceInfo)
|			    | // (1)从设备驱动列表内获取与设备moduleName相匹配设备驱动
|			    | // driverEntry = IDriverLoader:: GetDriverEntry();
|			    |-> driverEntry = HdfDriverLoaderGetDriverEntry()
|			    | // (2)创建 HdfDeviceNode 对象
|			    |-> devNode = HdfDeviceNodeNewInstance();
|			    | // (3)关联设备节点与设备驱动等
|			    |-> devNode->driverEntry = driverEntry;
|			    |-> devNode->deviceInfo = deviceInfo;
|			    |-> devNode->deviceObject.property = HcsGetNodeByMatchAttr(HdfGetRootNode(), 
|				|										deviceInfo->deviceMatchAttr);
|			    |-> devNode->deviceObject.priv = (void *)(deviceInfo->private);
|			    | // (4)绑定设备驱动IoService与设备服务
|			    |-> driverEntry->Bind(&devNode->deviceObject);
|
|-> devNode->hostService = hostService;

4.2 DevHostService将HdfDeviceNode挂载到HdfDevice的devNode链表

如下,在完成设备驱动的装载后,便调用DevHostService的Attach接口,将HdfDeviceNode挂载到HdfDevice的devNode链表:

// IDevHostService:: AddDevice();
DevHostServiceAddDevice()
|-> device = DevHostServiceGetDevice(hostService, deviceInfo->deviceId);
|-> devNode = driverLoader->LoadNode(driverLoader, deviceInfo);
|-> devNode->hostService = hostService;
|
| // IHdfDevice:: Attach
|-> HdfDeviceAttach()
	|-> DListInsertTail(&devNode->entry, &device->devNodes);
	|-> nodeIf->LaunchNode(devNode, devInst);

经过上面的过程,HdfDeviceNode和HdfDevice的对象关系图(并考虑到一对多的情况)可表示如下:

OpenHarmony驱动框架HDF中设备管理服务构建过程详解(二)-鸿蒙开发者社区

4.3 挂载HdfDeviceNode到Host的设备链表

在完成驱动匹配与装载后,其后便是初始化驱动,将设备服务发布到DevSvcManager,然后将HdfDeviceNode节点以Token的形式挂载到DevHostService在Manager域内的Client对象DevHostServiceClnt的devices链表,完成设备在DevMgrService上的注册,具体过程如下:

// IDeviceNode:: LaunchNode
HdfDeviceLaunchNode(struct HdfDeviceNode *devNode, struct IHdfDevice *devInst)
| // (1)初始化设备驱动
|-> driverEntry = HdfDriverLoaderGetDriverEntry()
|-> driverEntry->Init(&devNode->deviceObject);
| // (2)发布设备服务
|-> HdfDeviceNodePublishService()
| // (3)挂载deviceNode到DevHostServiceClnt对象的devices列表上,以token的形式
|-> deviceToken = devNode->token;
|-> DevmgrServiceClntAttachDevice()
    |-> struct DevmgrServiceClnt *inst = DevmgrServiceClntGetInstance();
    |-> devMgrSvcIf = inst->devMgrSvcIf;
    | // IDevmgrService:: AttachDevice
    |-> DevmgrServiceAttachDevice()
        |-> hostClnt = DevmgrServiceFindDeviceHost(inst, deviceInfo->hostId);
        |-> HdfSListAdd(&hostClnt->devices, &tokenClnt->node);

至此,完成了整个拼图的最后一块,将HdfDeviceNode以Token的形式挂载到DevHostServiceClnt的Device链表中,如下:

OpenHarmony驱动框架HDF中设备管理服务构建过程详解(二)-鸿蒙开发者社区

总结

在DevMgrService的构建过程中涉及了众多的对象类型,这些对象类型间的关系有大量借鉴了一些面向对象编程的类、接口、类继承、单例类等的编程思想,本来使用C语言实现面向对象编程的思维就已经使得C编程错综复杂,经常跨层,不太符合Linux内核分层分模块的习惯,增加了代码阅读的难度。而融入的“C/S设计模式”和“观察者设计模式”,无疑又使得阅读HDF的代码难度增加。

更多原创内容请关注:深开鸿技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
2
收藏 5
回复
举报
1条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

感谢大佬讲解,大图有点看不清,方便传一份到附件中吗?

回复
2022-5-20 14:16:21
回复
    相关推荐