- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
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">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
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">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
至此,完成了整个拼图的最后一块,将HdfDeviceNode以Token的形式挂载到DevHostServiceClnt的Device链表中,如下:

总结
在DevMgrService的构建过程中涉及了众多的对象类型,这些对象类型间的关系有大量借鉴了一些面向对象编程的类、接口、类继承、单例类等的编程思想,本来使用C语言实现面向对象编程的思维就已经使得C编程错综复杂,经常跨层,不太符合Linux内核分层分模块的习惯,增加了代码阅读的难度。而融入的“C/S设计模式”和“观察者设计模式”,无疑又使得阅读HDF的代码难度增加。
如果大家想更加深入的学习 OpenHarmony(鸿蒙南向) 开发的全栈内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

- 搭建开发环境
- Windows 开发环境的搭建
- Ubuntu 开发环境搭建
- Linux 与 Windows 之间的文件共享
- ……

- 构建子系统
- 启动流程
- 子系统
- 分布式任务调度子系统
- 分布式通信子系统
- 驱动子系统
- ……



写在最后
- 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:
https://qr21.cn/FV7h05

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">
微信名片
评论记录:
回复评论: