DevHostService与DevHostServiceClnt关联关系如下图:

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);
    |->  }
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

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);
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

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

为按照文章开始的对象类型关系图叙述对象类型实体的创建过程,上面只描述了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;
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

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);
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

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

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);

 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

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

总结

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

如果大家想更加深入的学习 OpenHarmony(鸿蒙南向) 开发的全栈内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

系统架构分析:https://qr18.cn/CgxrRy

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

写在最后

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/maniuT/article/details/139866319","extend1":"pc","ab":"new"}">> id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type2" id="blog_extension"> class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}"> class="blog_extension_card_left"> class="blog_extension_card_cont"> 鸿蒙开发学习资料领取!!! class="blog_extension_card_cont_r"> 微信名片
注:本文转载自blog.csdn.net的沧海一笑-dj的文章"https://blog.csdn.net/dengjin20104042056/article/details/99887816"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!