色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

鴻蒙HDF架構:DeviceManager如何生成所有的host配套設施

鴻蒙系統HarmonyOS ? 來源:oschina ? 作者:悠然紅茶侯亮 ? 2020-10-14 14:01 ? 次閱讀

我們闡述了在啟動DeviceManager這個核心服務時,是如何生成所有的host配套設施的,下面我們來進一步剖析細節。

我們已經知道,一個Host對應一個DevHostServiceClnt和一個DevHostService,很明顯主要行為都包含在后者內部。當后者啟動時,會執行到DriverInstallerStartDeviceHost(),該函數又會調用DevHostServiceStartServie(),這些內容在前一篇文章里都說過。

我們不用去想太多調用細節,反正說起來就是要讓一個DevHostServiceClnt和一個DevHostService“掛接”(attach)起來,掛接的動作里會進一步在DevHostService里安裝設備驅動。這個掛接動作具體對應的函數就是DevmgrServiceClntAttachDeviceHost()。在上一篇文章里,我們沒有展開講這個函數,現在就從它說起。為了便于閱讀,我將掛接動作的調用順序先繪制出來,如下圖所示:

1.掛接device Host

我用黃色框表達了DevmgrServiceClntAttachDeviceHost()一步,該函數代碼截選如下:

【drivers/hdf/frameworks/core/host/src/Devmgr_service_clnt.c】

int DevmgrServiceClntAttachDeviceHost(uint16_t hostId, struct IDevHostService *hostService)

{

struct IDevmgrService *devMgrSvcIf = NULL;

。 . 。 . 。 .

devMgrSvcIf = inst-》devMgrSvcIf;

。 . 。 . 。 .

// 實際調用的是DevmgrServiceAttachDeviceHost()

return devMgrSvcIf-》AttachDeviceHost(devMgrSvcIf, hostId, hostService);

}

最后一句實際調用的是DevmgrServiceAttachDeviceHost(),代碼截選如下:

【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】

static int DevmgrServiceAttachDeviceHost(

struct IDevmgrService *inst, uint16_t hostId, struct IDevHostService *hostService)

{

struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);

。 . 。 . 。 .

hostClnt-》deviceInfos = HdfAttributeManagerGetDeviceList(hostClnt-》hostId, hostClnt-》hostName);

。 . 。 . 。 .

hostClnt-》hostService = hostService;

return DevHostServiceClntInstallDriver(hostClnt);

}

首先,遍歷DevmgrService的hosts列表,根據hostId找到對應的DevHostServiceClnt對象,并給該DevHostServiceClnt對象的deviceInfos域和hostService域賦值,然后調用重頭戲DevHostServiceClntInstallDriver()。

在獲取這個host范疇的所有device信息時,也是去查詢上一篇文章提到的配置樹,樹節點的類型為DeviceResourceNode,只不過上一次系統是去查找具有“hdf_manager”屬性的節點,而此次是查找名字為hostName的節點,這個節點里包含著若干設備的信息,現在這些設備信息會被組織成一個HdfDeviceInfo鏈表。最終形成下面圖中的結構:

1.1安裝host范疇內的設備驅動

1.1.1在每個host的DevHostService里添加設備

Attach動作的最后一步就是安裝驅動啦,我們看一下這個DevHostServiceClntInstallDriver()函數:

【drivers/hdf/frameworks/core/manager/src/Devhost_service_clnt.c】

int DevHostServiceClntInstallDriver(struct DevHostServiceClnt *hostClnt)

{

。 . 。 . 。 .

struct HdfSListIterator it;

struct HdfDeviceInfo *deviceInfo = NULL;

struct IDevHostService *devHostSvcIf = NULL;

。 . 。 . 。 .

devHostSvcIf = (struct IDevHostService *)hostClnt-》hostService;

。 . 。 . 。 .

HdfSListIteratorInit(&it, hostClnt-》deviceInfos);

while (HdfSListIteratorHasNext(&it)) {

deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&it);

if ((deviceInfo == NULL) || (deviceInfo-》preload != DEVICE_PRELOAD_ENABLE)) {

continue;

}

// 實際調用的是 DevHostServiceAddDevice()

ret = devHostSvcIf-》AddDevice(devHostSvcIf, deviceInfo);

。 . 。 . 。 .

}

return HDF_SUCCESS;

}

其實就是遍歷一下該host范疇內的所有HdfDeviceInfo節點,如果節點的preload是“使能”的,就執行對應的AddDevice操作,即DevHostServiceAddDevice()函數,其代碼截選如下:

【drivers/hdf/frameworks/core/host/src/Devhost_service.c】

static int DevHostServiceAddDevice(struct IDevHostService *inst,

const struct HdfDeviceInfo *deviceInfo)

{

int ret = HDF_FAILURE;

struct HdfDevice *device = NULL;

struct HdfDeviceNode *devNode = NULL;

struct DevHostService *hostService = (struct DevHostService *)inst;

struct IDriverLoader *driverLoader = HdfDriverLoaderGetInstance();

。 . 。 . 。 .

device = DevHostServiceGetDevice(hostService, deviceInfo-》deviceId);

。 . 。 . 。 .

// 實際調用的是 HdfDriverLoaderLoadNode()

devNode = driverLoader-》LoadNode(driverLoader, deviceInfo);

。 . 。 . 。 .

devNode-》hostService = hostService;

// 實際調用的是 HdfDeviceAttach()

ret = device-》super.Attach(&device-》super, devNode);

。 . 。 . 。 .

return HDF_SUCCESS;

。 . 。 . 。 .

}

在這個函數里,先調用DevHostServiceGetDevice()嘗試從DevHostService的devices列表里查找與deviceId匹配的節點,如果找不到就創建一個新HdfDevice節點,并插入該列表。

當然,一開始devices列表是個空列表,此時只會創建新節點。反正經此一步,我們一般可以拿到一個可用的HdfDevice對象。接著利用驅動加載器加載一個和deviceInfo匹配的HdfDeviceNode節點。最后還需把得到的HdfDevice和HdfDeviceNode掛接起來。

1.1.1.1加載HdfDeviceNode

加載HdfDeviceNode的動作實際上是HdfDriverLoaderLoadNode(),代碼截選如下:

【drivers/hdf/frameworks/core/host/src/Hdf_driver_loader.c】

static struct HdfDeviceNode *HdfDriverLoaderLoadNode(

struct IDriverLoader *loader, const struct HdfDeviceInfo *deviceInfo)

{

struct HdfDriverEntry *driverEntry = NULL;

struct HdfDeviceNode *devNode = NULL;

。 . 。 . 。 .

// 實際調用的是 HdfDriverLoaderGetDriverEntry()

driverEntry = loader-》GetDriverEntry(deviceInfo);

。 . 。 . 。 .

devNode = HdfDeviceNodeNewInstance();

。 . 。 . 。 .

devNode-》driverEntry = driverEntry;

devNode-》deviceInfo = deviceInfo;

devNode-》deviceObject.property = HcsGetNodeByMatchAttr(HcsGetRootNode(),

deviceInfo-》deviceMatchAttr);

。 . 。 . 。 .

if ((deviceInfo-》policy == SERVICE_POLICY_PUBLIC) || (deviceInfo-》policy == SERVICE_POLICY_CAPACITY)) {

。 . 。 . 。 .

if (driverEntry-》Bind(&devNode-》deviceObject) != 0) {

HDF_LOGE(“bind driver failed”);

HdfDeviceNodeFreeInstance(devNode);

return NULL;

}

}

return devNode;

}

HdfDeviceNode的定義如下:

【drivers/hdf/frameworks/core/host/include/Hdf_device_node.h】

struct HdfDeviceNode {

struct IDeviceNode super;

struct HdfSListNode entry;

struct PowerStateToken *powerToken;

struct DevHostService *hostService;

struct HdfDeviceObject deviceObject;

struct IHdfDeviceToken *token;

struct HdfDriverEntry *driverEntry;

const struct HdfDeviceInfo *deviceInfo;

};

可以看到,驅動加載器在創建HdfDeviceNode節點時,還是有一些工作要做的:

1)得加載相應設備的驅動程序入口,最終體現為HdfDriverEntry;

2)創建一個HdfDeviceNode對象,經過研究,我們可以看到最終創建的其實是HdfDeviceNode的派生類(DeviceNodeExt)對象;

3)把HdfDeviceNode節點和設備驅動程序綁定起來;

1.1.1.1.1獲取驅動入口

驅動加載器獲取HdfDriverEntry的實際動作是HdfDriverLoaderGetDriverEntry():

【drivers/hdf/lite/manager/src/Lite_driver_loader.c】

struct HdfDriverEntry *HdfDriverLoaderGetDriverEntry(

const struct HdfDeviceInfo *deviceInfo)

{

int count = (int) (((uint8_t *)(HDF_DRIVER_END()) - (uint8_t *)(HDF_DRIVER_BEGIN())) / sizeof(size_t));

size_t *addrBegin = (size_t*)(HDF_DRIVER_BEGIN());

if ((deviceInfo == NULL) || (deviceInfo-》moduleName == NULL) || (deviceInfo-》svcName == NULL)) {

HDF_LOGE(“Hdf get device entry failed, input deviceInfo is NULL!”);

return NULL;

}

for (int i = 0; i 《 count; i++) {

struct HdfDriverEntry *driverEntry = (struct HdfDriverEntry *)(*addrBegin);

if (strcmp(deviceInfo-》moduleName, driverEntry-》moduleName) == 0) {

return driverEntry;

}

addrBegin++;

}

HDF_LOGE(“Hdf get %s device entry failed!”, deviceInfo-》svcName);

return NULL;

}

其中,HdfDriverEntry的定義如下:

【drivers/hdf/frameworks/include/core/Hdf_device_desc.h】

struct HdfDriverEntry {

int32_t moduleVersion;

const char *moduleName;

int32_t (*Bind)(struct HdfDeviceObject *deviceObject);

int32_t (*Init)(struct HdfDeviceObject *deviceObject);

void (*Release)(struct HdfDeviceObject *deviceObject);

};

現在我們來解釋一下,HdfDriverLoaderGetDriverEntry()到底在干什么。我們設想,HDF會先加載需要的所有驅動程序,每個驅動程序內部都會構造一個HdfDriverEntry對象,而且會填好那個Bind域,這其實就是在填寫一個回調函數指針,當然,也只有驅動程序自己知道該填寫哪個函數指針。

HDF會把加載的所有驅動的HdfDriverEntry對象的起始地址匯總起來,形成一個類似地址數組的東西,這個數組的第一項的地址對應上面代碼中的HDF_DRIVER_BEGIN(),最后一項的地址對應HDF_DRIVER_END()(最后一項不填內容)。示意圖如下:

獲取驅動入口時,就是在遍歷這個指針數組,查詢與moduleName匹配的節點。

1.1.1.1.2 創建HdfDeviceNode對象

接著嘗試創建HdfDeviceNode對象,此時調用的HdfDeviceNodeNewInstance()函數如下:

【drivers/hdf/frameworks/core/host/src/Hdf_device_node.c】

struct HdfDeviceNode *HdfDeviceNodeNewInstance()

{

return (struct HdfDeviceNode *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVICE_SERVICE);

}

又需要去查我們熟悉的對象創建表(g_liteObjectCreators),最終查到會調用DeviceNodeExtCreate():

【drivers/hdf/lite/manager/src/Hdf_device_node_ext.c】

struct HdfObject *DeviceNodeExtCreate()

{

struct DeviceNodeExt *instance =

(struct DeviceNodeExt *)OsalMemCalloc(sizeof(struct DeviceNodeExt));

if (instance != NULL) {

DeviceNodeExtConstruct(instance);

instance-》ioService = NULL;

}

return (struct HdfObject *)instance;

}

可以看到,實際創建的是一個DeviceNodeExt對象。DeviceNodeExt繼承于HdfDeviceNode,定義如下:

【drivers/hdf/lite/include/manager/Hdf_device_node_ext.h】

struct DeviceNodeExt {

struct HdfDeviceNode super;

struct HdfIoService *ioService;

};

其構造函數如下:

【drivers/hdf/lite/manager/src/Hdf_device_node_ext.c】

static void DeviceNodeExtConstruct(struct DeviceNodeExt *inst)

{

struct IDeviceNode *nodeIf = (struct IDeviceNode *)inst;

if (nodeIf != NULL) {

HdfDeviceNodeConstruct(&inst-》super);

nodeIf-》PublishService = DeviceNodeExtPublishService;

}

}

注意,它修改了繼承來的PublishService域,將函數指針設為DeviceNodeExtPublishService了。

HdfDriverLoaderLoadNode()會給DeviceNodeExt的driverEntry域、deviceInfo域、deviceObject.property賦值,那么在進行綁定之前,DeviceNodeExt的示意圖大概是這樣的:

1.1.1.1.3 綁定驅動入口

接下來要將剛剛創建的DeviceNodeExt節點和驅動入口綁定起來:

driverEntry-》Bind(&devNode-》deviceObject)

前文我們已經說了,每個程序會實現自己的Bind動作,而HDF只負責回調Bind。注意,回調時HDF需要傳入DeviceNodeExt節點的deviceObject部分的指針,因為需要驅動程序填寫其中的域。當然,我們從上圖中可以看到,deviceObject部分只剩下service域(IDeviceIoService*)需要填寫。那么很明顯,一個驅動程序要能被HDF使用,那么它就得包含一個IDeviceIoService對象。IDeviceIoService的定義如下:

【drivers/hdf/frameworks/include/core/Hdf_device_desc.h】

struct IDeviceIoService {

struct HdfObject object;

int32_t (*Open)(struct HdfDeviceIoClient *client);

int32_t (*Dispatch)(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,

struct HdfSBuf *reply);

void (*Release)(struct HdfDeviceIoClient *client);

};

現在我們可以基于前文示意圖,繪制一張DeviceNodeExt和驅動程序綁定后的示意圖了,如下圖:

1.1.1.2 掛接HdfDeviceNode

DevHostServiceAddDevice()在加載好DeviceNodeExt之后,調用了一句Attach:

ret = device-》super.Attach(&device-》super, devNode);

嘗試把HdfDevice節點和DeviceNodeExt聯系起來,這一句其實是調用HdfDeviceAttach(),相關代碼如下:

【drivers/hdf/frameworks/core/host/include/Hdf_device.h】

struct IHdfDevice {

struct HdfObject object;

int (*Attach)(struct IHdfDevice *, struct HdfDeviceNode *);

};

struct HdfDevice {

struct IHdfDevice super;

struct HdfSListNode node;

struct HdfSList services;

uint16_t deviceId;

uint16_t hostId;

};

【drivers/hdf/frameworks/core/host/src/Hdf_device.c】

static int HdfDeviceAttach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode)

{

struct HdfDevice *device = (struct HdfDevice *)devInst;

struct IDeviceNode *nodeIf = (struct IDeviceNode *)devNode;

。 . 。 . 。 .

HdfSListAdd(&device-》services, &devNode-》entry);

// 實際調用的是 HdfDeviceLaunchNode()

return nodeIf-》LaunchNode(devNode, devInst);

}

代碼里先將DeviceNodeExt添加進HdfDevice的services列表里,然后調用了HdfDeviceLaunchNode()。

我們前文已經說過,HdfDevice節點在之前已經添加進DevHostService的devices列表了,現在它又和DeviceNodeExt聯系起來了,再結合前文中的知識,我們可以畫一張大一點兒的關系示意圖了,如下:

至此,相信大家已經基本了解掛接設備host所形成的數據結構了,正如上圖所示,每個host都會對應上圖中紅、綠、藍三個范疇。大家不妨自己試著畫畫這張圖,看看還會發現什么。至于HDF的其他方面,我們可以在其他文章里再探討。
編輯:hfy

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4333

    瀏覽量

    62687
  • 設備驅動
    +關注

    關注

    0

    文章

    68

    瀏覽量

    10897
  • 鴻蒙系統
    +關注

    關注

    183

    文章

    2636

    瀏覽量

    66393
收藏 人收藏

    評論

    相關推薦

    【書籍評測活動NO.53】鴻蒙操作系統設計原理與架構

    的開源,全球開發者和廣大伙伴能更踴躍地協同共建鴻蒙社區,促進鴻蒙生態枝繁葉茂 ; 希望高校和科研院所能做好鴻蒙操作系統的人才培養,為國產操作系統及其生態的可持續發展提供堅實的支撐。 也希望所有
    發表于 12-16 15:10

    鴻蒙跨端實踐-JS虛擬機架構實現

    類似的框架,我們需要自行實現以確保核心基礎能力的完整。 鴻蒙虛擬機的開發經歷了從最初 ArkTs2V8 到 JSVM + Roma新架構方案 。在此過程中,我們實現了完整的鴻蒙版的“J2V8”和 基于系統JSVM的JS虛擬機框架
    的頭像 發表于 09-30 14:42 ?2435次閱讀
    <b class='flag-5'>鴻蒙</b>跨端實踐-JS虛擬機<b class='flag-5'>架構</b>實現

    聚徽觸控-多媒體教學一體機需要哪些配套設施

    多媒體教學一體機需要的配套設施主要包括以下幾個部分:
    的頭像 發表于 07-23 09:44 ?312次閱讀

    ESP32-WROOM-32UE為什么無法掃描所有的2.4G熱點?

    id040cfab35db4270c443146b19febf6c59266d419問題點:掃描到的熱點數量少(有些無法掃描到),同-環境下主控為imx8rm使用rt18723bu無線芯片能掃到周圍所有的2.4G頻段熱點 2.
    發表于 06-05 06:18

    最新開源代碼證實!“鴻蒙原生版”微信正在積極開發中

    , MMKV v1.3.5 首次正式支持 HarmonyOS NEXT, 目前大部分功能在該平臺上可正常使用。 據介紹,MMKV 用于保持內存與文件同步,最大限度地利用原生平臺來實現最佳性能,所有的更改都會
    發表于 05-08 17:08

    超融合基礎架構的軟硬件設計思路

    簡單來說,超融合基礎架構就是在業務節點上運行服務器虛擬化軟件和存儲虛擬化軟件,將所有的計算節點通過網絡聚合成一個統一的虛擬計算和虛擬存儲資源池,以資源池的形式提供數據中心所需的IT基礎設施
    的頭像 發表于 04-25 10:28 ?1830次閱讀
    超融合基礎<b class='flag-5'>架構</b>的軟硬件設計思路

    如何在Cubemx中添加所有的外設頭文件?

    ,需要自己去添加相應的頭文件,但自己添加有時還是會報錯,而且是不知原因的報錯。 所以,在這向各位開發者、大咖,請教一下,如何在Cubemx中添加所有的外設頭文件,或者在配置完cubemx后如何高效的添加自己所需要的外設頭文件
    發表于 04-01 07:46

    NVIDIA Edify多模態架構升級,引領視覺生成式AI新紀元

    NVIDIA近日宣布,其用于視覺生成式AI的多模態架構Edify迎來重大更新,為開發者和視覺內容提供商帶來前所未有的新功能。其中,3D資產生成功能的引入,極大地提升了AI圖像
    的頭像 發表于 03-27 10:22 ?471次閱讀

    SATA3.0 Host Controller IP介紹

    SATA3.0 Host IP不僅實現了SATA協議的PHY(物理層)、link(鏈路層)和TRN(傳輸層),并且實現了CMD(命令層)和APP(應用層),支持1.5、3和6Gbps傳輸速率
    發表于 02-27 15:53 ?0次下載

    Xilinx FPGA NVMe控制器,NVMe Host Controller IP

    NVMe Host Controller IP可以連接高速存儲PCIe SSD,無需CPU和外部存儲器,自動加速處理所有的NVMe協議命令,具備獨立的數據寫入AXI4-Stream/FIFO接口和數
    的頭像 發表于 02-18 11:27 ?914次閱讀
    Xilinx FPGA NVMe控制器,NVMe <b class='flag-5'>Host</b> Controller IP

    使用 Taro 開發鴻蒙原生應用 —— 快速上手,鴻蒙應用開發指南

    隨著鴻蒙系統的不斷完善,許多應用廠商都希望將自己的應用移植到鴻蒙平臺上。最近,Taro 發布了 v4.0.0-beta.x 版本,支持使用 Taro 快速開發鴻蒙原生應用,也可將現有的
    的頭像 發表于 02-02 16:09 ?891次閱讀
    使用 Taro 開發<b class='flag-5'>鴻蒙</b>原生應用 —— 快速上手,<b class='flag-5'>鴻蒙</b>應用開發指南

    華為鴻蒙系統怎么樣 華為鴻蒙系統和安卓系統的區別

    華為鴻蒙系統是華為公司自主研發的全場景分布式操作系統,于2019年8月首次發布。鴻蒙系統不同于傳統的操作系統,它以分布式應用架構為基礎,能夠在各種終端設備上實現流暢的交互體驗,并且具備更高的安全性
    的頭像 發表于 02-02 14:54 ?1756次閱讀

    鴻蒙OS和開源鴻蒙什么關系?

    開源鴻蒙(Open Harmony) 鴻蒙系統愿來的設計初衷,就是讓所有設備都可以運行一個系統,但是每個設備的運算能力和功能都不同,所以內核的設計上,采用了微內核的設計,除了最基礎的功能放在
    的頭像 發表于 01-30 15:44 ?1159次閱讀
    <b class='flag-5'>鴻蒙</b>OS和開源<b class='flag-5'>鴻蒙</b>什么關系?

    鴻蒙系統和安卓的區別 鴻蒙系統有什么特別之處

    鴻蒙系統是華為公司自主研發的一款全新操作系統,旨在替代安卓系統。鴻蒙系統與安卓系統在多個方面存在不同,下面將詳細介紹鴻蒙系統與安卓系統的區別以及鴻蒙系統的特別之處。 一、
    的頭像 發表于 01-18 11:45 ?1.2w次閱讀

    鴻蒙物聯網基礎

    關于物聯網架構以及鴻蒙第三方應用庫的引用方式
    的頭像 發表于 01-08 08:37 ?543次閱讀
    <b class='flag-5'>鴻蒙</b>物聯網基礎
    主站蜘蛛池模板: 国产精品嫩草影视在线观看| 啦啦啦视频在线观看WWW| 女人18毛片| 把极品白丝老师啪到腿软| 人人干人人爽| 国产精品免费大片一区二区| 夜色爽爽爽久久精品日韩| 美女张开腿让男生桶动态图| yellow视频免费观看高清在线| 撕开美女的衣服2| 久久成人精品免费播放| georgielyall装修工| 香蕉59tv视频| 麻豆成人啪啪色婷婷久久 | 中文字幕本庄优花喂奶| 欧美亚洲国产手机在线有码| 国产精品九九九久久九九| 亚洲欧美偷拍视频一区| 欧美精品一区二区蜜臀亚洲| 国产色情短视频在线网站| 中文在线中文资源| 日韩精品人成在线播放| 九九热综合| 成人在线视频在线观看| 一本到2v不卡区| 日日干夜夜艹| 妈妈的职业3完整版在线播放| 国产精品久久久久久久久久免费 | 毛片免费观看视频| 国产精品久久久久久免费播放| 在线中文字幕亚洲日韩| 玩高中女同桌肉色短丝袜脚文 | 御姐被吸奶| 小黄飞二人转| 奇米色偷偷| 久cao在线香蕉| 国产精品无码人妻在线| 99re6在线视频国产精品欧美| 亚洲精品123区在线观看| 日本少妇无码精品12P| 秘密教学93话恩爱久等了免费|