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.pswp.cn/news/696749.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/696749.shtml
英文地址,請注明出處:http://en.pswp.cn/news/696749.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

1.WEB滲透測試-前置基礎知識-ip地址

ip地址: ip地址指的是互聯網協議地址,是IP協議提供的一種統一的地址格式,以每一臺聯網的主機都有一個對應的ip地址,ip地址也可以理解為分配給用戶上網使用的網際協議的設備的數字標簽。通俗的來說就是你打電話時候的每個人都有自己…

AIGC 實戰:如何使用 Docker 在 Ollama 上離線運行大模型(LLM)

Ollama簡介 Ollama 是一個開源平臺,用于管理和運行各種大型語言模型 (LLM),例如 Llama 2、Mistral 和 Tinyllama。它提供命令行界面 (CLI) 用于安裝、模型管理和交互。您可以使用 Ollama 根據您的需求下載、加載和運行不同的 LLM 模型。 Docker簡介 D…

在Mac上搭建MongoDB環境

最近工作中需要裝MongoDB環境,搭建過程中遇到了一些問題,在這里記錄一下安裝MongoDB環境的方法以及問題的解決方法。有兩種安裝MongoDB的方法:brew安裝和手動安裝。 目錄 使用Homebrew安裝MongoDB 手動安裝MongoDB(不使用Homebr…

備戰藍橋杯 Day11(滾動數組優化+完全背包)

01背包的滾動數組優化 【題目描述】 經典0—1背包問題,有n個物品,編號為i的物品的重量為w[i],價值為c[i],現在要從這些物品中選一些物品裝到一個容量為m的背包中,使得背包內物體在總重量不超過m的前提下價值盡量大。 #include&…

python_數據分析_numpy庫

一、創建ndarray *ndarray是NumPy中表示數組的重要類型 1、使用np.array()創建 *參數列表:[1,2,3,4] 注:(1)、numpy默認ndarray的所有元素的類型是相同的 ? (2)、如果傳入的數據類型不同,會被按照優先級強制轉換為同一類型,其…

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…

多普勒變化率的應用 與 FPGA

1.多普勒變化率是一個描述波源和觀察者相對速度變化的物理量&#xff0c;它與加速度有關。 多普勒效應是指當波源和觀察者之間存在相對運動時&#xff0c;觀察者接收到的波頻率與波源發射的頻率之間的差異。這種現象在聲波、電磁波等多種波動中都會出現。多普勒變化率通常用來…

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

【OCR專題文章】

目錄 一、數據獲取及預處理方法篇 二、兩階段算法篇(檢測識別) 三、一階段算法篇(Enc-Dec) 四、拓新篇 本欄聚焦在OCR的相關算法&#xff0c;專欄內文章的代碼均已實現。 一、數據獲取及預處理方法篇 【數據獲取】 合同數據獲取&#xff1a;【OCR】【專題系列】二、數據獲取-…

解決windows無法訪問wsl下docker服務

筆者在初學使用wsl跑docker時,遇到了windows無法訪問的問題,并且瀏覽了大部分的文章,發現并沒有起效,在反復試錯終于成功之后,總結為以下幾點: 1.升級至wsl2 2.將.wslconfig文件(用戶文件夾下)中的如下鏡像服務關閉刪除 networkingModemirrored 3.打開wsl防火墻相應的端口 …

記錄解決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;…

【Day55】代碼隨想錄之動態規劃_買賣股票含冷凍期和手續費

文章目錄 動態規劃理論基礎動規五部曲&#xff1a;出現結果不正確&#xff1a; 1. 最佳買賣股票的時機含冷凍期2. 買賣股票的最佳時機含手續費 動態規劃理論基礎 動規五部曲&#xff1a; 確定dp數組 下標及dp[i] 的含義。遞推公式&#xff1a;比如斐波那契數列 dp[i] dp[i-1…

【Elasticsearch專欄 01】深入探索:Elasticsearch的正向索引和倒排索引是什么

文章目錄 什么是Elasticsearch的正向索引和倒排索引&#xff1f;1.倒排索引&#xff08;Inverted Index&#xff09;2.正向索引&#xff08;Forward Index&#xff09;3.小結 什么是Elasticsearch的正向索引和倒排索引&#xff1f; 首先&#xff0c;要明確的是&#xff0c;Ela…

leetcode:78.子集

1.樹形結構&#xff1a;往后依次取該數字往后的數字&#xff08;前面的不要取&#xff0c;否則子集會重復&#xff09;&#xff1b;每一層遞歸的結果都要放入結果集&#xff0c;而并非只放葉子節點。 代碼實現&#xff1a; #達到了葉子節點&#xff08;終止條件&#xff09; …