自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Hi3861的SAMGR--系統(tǒng)服務框架子系統(tǒng)-2

系統(tǒng)
文章由鴻蒙社區(qū)產出,想要了解更多內容請前往:51CTO和華為官方戰(zhàn)略合作共建的鴻蒙技術社區(qū)https://harmonyos.51cto.com

[[404768]]

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區(qū)

https://harmonyos.51cto.com

 接前文《Hi3861的SAMGR--系統(tǒng)服務框架子系統(tǒng)-1

4 結構體的分解

4.1 先上samgr的展開圖【附件有原圖】

4.2 Samgr:SamgrLiteImpl g_samgrImpl

  1.      typedef struct SamgrLiteImpl SamgrLiteImpl; 
  2.         struct SamgrLiteImpl  { 
  3. A:          SamgrLite vtbl;       //SAMGR_GetInstance() return this SamgrLite Instance 
  4. B:          MutexId mutex; 
  5. C:          BootStatus status;    //see BootStatus 
  6. D:          Vector services;      //a vector to record all services 
  7. E:          TaskPool *sharedPool[MAX_POOL_NUM]; 
  8.         }; 

 注冊第一個服務的時候,首先要通過SAMGR_GetInstance()從全局變量g_samgrImpl獲取一個samgr的實例對象,g_samgrImpl已經初始化過了的話,可以直接返回samgr對象的引用,g_samgrImpl沒有初始化的話,就需要通過Init函數(shù)進行初始化相關的配置之后,才能返回samgr對象的引用。

以后的各種service/feature的操作,基本是都是需要通過g_samgrImpl進行管理的。下面把這個全局變量展開來看一下:

A: SamgrLite vtbl;

vtbl 就是SamgrLite 的實例,SAMGR_GetInstance() 時,返回的就是指向它的指針。SamgrLite結構體(或者直接說類)定義了四組十個函數(shù)指針,如下圖,同一組用同一個顏色框起來:

在g_samgrImpl的初始化(init)時與對應的實現(xiàn)函數(shù)對應關聯(lián)起來,之后就可以通過這四組函數(shù)來對service/ feature進行注冊、注銷、獲取API等操作了。

而具體的service、feature在各自INIT時,會通過g_samgrImpl的samgr實例調用這里的Register接口,向g_samgrImpl注冊自己和API,把自己納入samgr的管理體系中,然后就是samgr為service、feature創(chuàng)建queue/taskpool/task等運行環(huán)境了。

B: MutexId mutex;

互斥鎖。關鍵代碼段的操作要加鎖,保證多線程下對共享數(shù)據(jù)的操作的完整性。

在g_samgrImpl的初始化(init)時就會通過MUTEX_InitValue() 生成互斥鎖,MUTEX_InitValue()聲明在thread_adapter.h,它的實現(xiàn)則取決于平臺使用的內核,M核平臺用cmsis接口來實現(xiàn),A核/Linux平臺,則使用posix接口來實現(xiàn)。

類似的還有內存、隊列、線程、timer的相關操作,代碼見:

  1. Hi3861/foundation/distributedschedule/samgr_lite/samgr/adapter/ 

理論上,全局對象g_samgrImpl初始化(init)時就會生成一個mutex,且只要g_samgrImpl沒有重新初始化,這個mutex就應該是不變的,Hi3861平臺上我看到的也確實如此。

但是Hi3516平臺上我看到了一個奇怪的地方,見前文《鴻蒙系統(tǒng)框架層的啟動細節(jié)》的附件log,搜索關鍵字“SAMGR_GetInstance|StartServiceByName|Invoke: msg”可以看到:

有若干處mutex是為NULL的,需要重新初始化g_samgrImpl,這樣豈不是會把之前注冊的service Vector/TaskPool等清除掉嗎?先存疑,待進一步仔細閱讀Hi3516的代碼后再確認。

C: BootStatus status;

系統(tǒng)的啟動階段狀態(tài)標記。

Hi3861平臺上電啟動到 system_init.c 的

  1. void HOS_SystemInit(void) 
  2.     ...... 
  3.     SYS_INIT(service); 
  4.     SYS_INIT(feature); 
  5.     SAMGR_Bootstrap(); 

 這一步時,通過SYS_INIT() 啟動的都是用SYS_SERVICE_INIT()和SYS_FEATURE_INIT() 標記的service和feature,而通過SYSEX_SERVICE_INIT/APP_SERVICE_INIT/ SYSEX_FEATURE_INIT/APP_FEATURE_INIT 標記的service和feature,則會在系統(tǒng)啟動到 BOOT_APP 這一步時,由Bootstrap service來啟動,見 bootstrap_service.c 的MessageHandle()函數(shù)內的 INIT_APP_CALL() 的調用:

系統(tǒng)啟動狀態(tài)標記到 BOOT_DYNAMIC 這一步時,意味著系統(tǒng)所有的應用服務也啟動完畢了,進入了一個比較穩(wěn)定的狀態(tài),至于BOOT_DYNAMIC狀態(tài)還會做其他什么事情,我暫時還沒有更多的了解。

為了理解例程代碼如何工作,我在這里加了 BOOT_DEBUG和BOOT_DEBUG_WAIT兩個狀態(tài),用來調用例程里的INIT_TEST_CALL(),跑相關的測試流程,通過相關的log來驗證自己的分析,詳見附件的log。

D: Vector services;

g_samgrImpl 初始化時:

  1. g_samgrImpl.services = VECTOR_Make((VECTOR_Key)GetServiceName, (VECTOR_Compare)strcmp); 

創(chuàng)建了一個Vector:{0, 0, 0, NULL, key, compare},Vector的定義如下:

其中:

  • max:表示下面的**data指針數(shù)組的大小,也就是data[max]所能存儲的最大指針數(shù)目;
  • top: 當前使用到了的指針數(shù)組的最高位置data[top],當top==max,同時free為0時,表示data[max]已經裝滿了,需要擴容,一次擴容增加4個element位置,變成data[max+4],詳情見VECTOR_Add()函數(shù)的實現(xiàn)。
  • free:當前0~top之間,釋放了的位置的數(shù)量。當已注冊在冊的service unregister時,對應記錄這個service的data[i]會被清空,free+1;下次有新的service注冊時,會優(yōu)先使用data[i]來記錄新service的Impl對象指針,free-1。詳情見VECTOR_Swap()函數(shù)的實現(xiàn)
  • **data:指針數(shù)組data[max],每一個data[i]記錄了一個注冊進來的service對應的ServiceImpl 對象的指針,初始化為NULL,通過VECTOR_Add()函數(shù)內的操作擴容。
  • key:是samgr_lite.c定義的GetServiceName(ServiceImpl*)函數(shù)指針,它可以通過參數(shù)來獲取對應的service Name。
  • compare:是strcmp函數(shù)指針,也就是string標準庫提供的字符串比較函數(shù)。

Samgr通過這個Vector來管理所有注冊進來的service(實際上管理的是serviceImpl對象,通過serviceImpl來關聯(lián)具體的service和service對應的feature)。

每個service可以有0個/1個或多個feature,每個service(serviceImpl對象)也是通過自己的Vector來管理feature。

對Vector的操作,全部定義在:

Hi3861/foundation/distributedschedule/services/samgr_lite/samgr/source/common.c

里面了,需要仔細閱讀分析,去理解相關操作。

下面是幾處要點:

  • VECTOR_Make() 會創(chuàng)建一個{0, 0, 0, NULL, key, compare} Vector,當需要往Vector中添加element時,會在VECTOR_Add()中擴容。
  • VECTOR_Add(Vector *vector, void *element) 的時候,發(fā)現(xiàn)Vector的data[max] 空間用盡了,就會重新申請一塊增大了4個element的內存空間Newdata[max+4],把舊的data[x]全部拷貝進去(還有4個新的空余的element位置),g_samgrImpl.services.data重新指向Newdata,再把舊的data[x]占用的空間釋放掉,這樣,新的element (ServiceImpl 對象的指針)就可以記錄進來了。
  • VECTOR_Swap()用來刪除一個已經記錄在案的element(也就是unregister一個service),把它對應的 data[x] 置為NULL,free+1,空出的位置會給未來新注冊的service 優(yōu)先使用。
  • VECTOR_Find()/VECTOR_FindByKey() 可以查找element(serviceImpl),并返回它的index。

特別是VECTOR_FindByKey(Vector *vector, const void *key),第二個參數(shù)“void *key”實際上是一個service的名字字符串,如“Broadcast”。

FindByKey會循環(huán)獲取data[0~top]的ServiceImpl 對象的指針,并將其作為key函數(shù)指針(GetServiceName())的參數(shù)來獲取service的Name,將Name其與上面的第二個參數(shù)的service Name,用compare函數(shù)指針(strcmp)進行對比,匹配則返回對應的data[i]的 index i。

E: TaskPool *sharedPool[MAX_POOL_NUM]; // MAX_POOL_NUM 是8

Hi3861平臺啟動到 system_init.c 的最后一步時:

  1. void HOS_SystemInit(void) 
  2.     ...... 
  3.     SAMGR_Bootstrap();   

 調用SAMGR_Bootstrap()去啟動已經注冊了的service,會為service創(chuàng)建queue和taskPool資源,每個service有一個GetTaskConfig()接口,可以返回這個service運行起來的task配置參數(shù),如 bootstrap service的TaskConfig為:

請自行查看 TaskConfig的定義。

這里需要關注的是 SHARED_TASK 這個標記,在samgr的 AddTaskPool()這一步時:

bootstrap service的TaskConfig配置會被修改成默認的DEFAULT_TASK_CFG,意味著在bootstrap_service.c 中定義的TaskConfig 參數(shù)(stackSize和queueSize)其實并沒有起作用,想要修改SHARED_TASK的stackSize和queueSize,要去修改DEFAULT_TASK_CFG的配置。

而上面case SHARED_TASK的操作以及g_samgrImpl.sharedPool[]的存在,可以為若干個共同標記了SHARED_TASK的service共享一個Queue和taskPool資源(這樣可以節(jié)約好多資源),TaskEntry在Queue中收到msg時,可以通過Exchange 消息里面的Identity字段解析出Sid/Fid/Qid信息,以此來確認到底是哪個service/feature需要處理這個消息。

TaskConfig里的priority字段,則確定了service用的是哪個sharePool[x],優(yōu)先級越高,x越大。

我在代碼里全局搜索了一下“SHARED_TASK”關鍵字,得到如下結果:

主要是在samgr例程里,不同優(yōu)先級別的service,共享著不同x的sharedPool[x]資源。

不是SHARED_TASK的service則有自己獨立的Queue和taskPool,不會直接記錄在g_samgrImpl.sharedPool[]里,而是記錄在各自service的serviceImpl對象的taskPool* 里。

4.3 ServiceImpl 類

  1.     struct ServiceImpl { 
  2. A:      Service*      service; 
  3. B:      IUnknown* defaultApi; 
  4. C:      TaskPool*   taskPool; 
  5. D:      Vector    features; 
  6. E:      int16      serviceId; 
  7. F:      uint8      inited; 
  8. G:      Operations ops; 
  9.     }; 

 g_samgrImpl 全局變量的services Vector里,只直接記錄ServiceImpl對象的指針,并不直接記錄和管理service、feature對象本身。service在向samgr注冊自己時,samgr會首先生成一個ServiceImpl對象,將service對象的指針記錄在ServiceImpl的Service* service里,而ServiceImpl對象本身的指針,則記錄在g_samgrImpl.services.data[i] 中,這樣就建立了g_samgrImpl 到具體service的聯(lián)系,見本文上面的展開圖。

A: Service* service;    

指向當前ServiceImpl對象所對應的具體的service對象,這些具體的service對象都是Service類的子類對象。

B: IUnknown* defaultApi;

繼承了IUnknown接口(INHERIT_IUNKNOWN)的service或者feature,都會有IUnknown的一組三個默認的接口,這組接口主要是記錄service/feature對象的引用數(shù)量,還可以通過其中的QueryInterface接口實現(xiàn)父類(IUnknown)指針到具體的service/feature子類對象指針的類型轉換,以獲取子類提供的功能。

詳情見下面對IUnknown的分析。

我在《鴻蒙的DFX子系統(tǒng) 》一文中,有對hiview service做過一個展開,可以去那里了解一下。

C: TaskPool* taskPool;

這就是上一小節(jié)中,samgr為service創(chuàng)建的taskPool的指針(同時創(chuàng)建的還有消息隊列,queueId同時保存在taskPool里面)。

如果service task是SHARED_TASK類型的,那就會有多個service共享一個taskPool和queue,這里的taskPool指針就會指向同一塊內存空間,同時,g_samgrImpl的對應優(yōu)先級別的sharedPool[x]也會記錄著這個taskPool指針。

如果service task不是SHARED_TASK類型的,那就只會在這里記錄service的taskPool(包括queue),而不會在g_samgrImpl中做記錄。

D: Vector features;

feature需要依賴于對應的service才能注冊和運行,一個service可以有0個、1個或多個feature。service本身不記錄它對應的feature的信息,而是由這個ServiceImpl.features來記錄。ServiceImpl 的這個Vector features類似于g_samgrImpl用于記錄serviceImpl的Vector services。

一個service沒有feature時,features Vector就保持初始化的樣子,對應的features.data 是NULL。

一個service有若干個feature時,就會在feature注冊時,由samgr生成對應FeatureImpl類對象,將此對象與具體的feature關聯(lián)起來,再將此對象的指針保存在Vector features.data[x]里,并將這個 x 作為對應feature的ID,另做保存。以后samgr就可以通過它自己的vector找到serviceImpl,再進一步通過這個vector找到對應的featureImpl,從而找到最終的feature。

E: int16 serviceId;

當前的ServiceImpl 對象指針保存在g_samgrImpl.services vector內的data[x]上的這個 x 序號,就作為當前service的ID,保存在這里。這個serviceId也可能同時保存在具體的service對象的Identity 結構體里。

F: uint8 inited;

標記當前ServiceImpl 對應的service的狀態(tài),service沒有init起來是不能注冊feature的,service在處理消息事件的時候,狀態(tài)也要對應置為 BUSY,處理完消息又要將狀態(tài)寫回IDLE。具體可自行查閱代碼。

G: Operations ops;

主要記錄了service處理消息事件的時間戳、msg數(shù)量(編號?)、步驟和是否存在異常等信息,估計與跨設備的服務/消息處理的同步有關,對此暫未做深入理解,待作進一步的理解。

4.4 FeatureImpl類

  1.   typedef struct FeatureImpl FeatureImpl; 
  2.     struct FeatureImpl { 
  3. A:      Feature  *feature; 
  4. B:      IUnknown *iUnknown; 
  5.     }; 

 FeatureImpl 類看起來相對簡單,直接是一個Feature指針(A)指向對應的具體的feature對象。

有些feature除了繼承自Feature類之外,還繼承了某些interface,為feature提供額外的功能,這些interface 都是繼承了最原始的IUnknown接口類(INHERIT_IUNKNOWN)。

這里的IUnknown *iUnknown與上面的ServiceImpl 的IUnknown* defaultApi; 其實是同一個東西,它們都指 向了一個feature或者service所繼承/實現(xiàn)的接口中,IUnknown接口所在的位置,見上面ServiceImpl對IUnknown* defaultApi;的說明。

更多詳情見下面對IUnknown的分析。

4.5 Service類及其子類

  1. struct Service { 
  2.     const char *(*GetName)(Service *service);                   //獲取service名稱 
  3.     BOOL (*Initialize)(Service *service, Identity identity);    //service的初始化 
  4.     BOOL (*MessageHandle)(Service *service, Request *request);  //service的消息處理函數(shù) 
  5.     TaskConfig (*GetTaskConfig)(Service *service);              //獲取service 任務運行的配置 

 Service類是所有service類的父類,它聲明了四個函數(shù)指針,這是每一個服務都必須要實現(xiàn)的生命周期函數(shù),見上面的注釋。

每一個具體的服務類都繼承自這個Service類,然后可以擴展自己獨特的功能。

下面分別看一下Hi3861默認的三個具體的服務。

A: Bootstrap service

  1. typedef struct Bootstrap { 
  2.     INHERIT_SERVICE;  //繼承上面的Sevice類 
  3.     Identity identity;   //bootstrap service對象的id信息 
  4.     uint8 flag; 
  5. } Bootstrap; 

 Bootstrap 除了繼承Service之外,還增加了一個Identity identity 和 uint8 flag。

  • Identity identity

這是Bootstrap service具體對象的身份信息,里面包括了: serviceId/featureId/queueId三個信息。

serviceId:Bootstrap service 對應的 serviceImpl對象,在g_samgrImpl.services這個Vector.data[]中存放位置 的index,這里值為0.

featureId:Bootstrap service不帶feature,所以值為 -1。

queueId: Bootstrap service啟動時,samgr會為其創(chuàng)建消息隊列,這就是消息隊列的ID,是一串數(shù)字。

  • uint8 flag

一個標記,主要是LOAD_FLAG 0x01這一個位,用來標記非系統(tǒng)service/feature是否已經加載和注冊,見 bootstrap_service.c的MessageHandle()內對flag的使用。

B. Broadcast service

  1. typedef struct BroadcastService BroadcastService; 
  2. struct BroadcastService { 
  3.     INHERIT_SERVICE; 
  4. }; 

 Broadcast service僅僅直接繼承了Service類,確保它的service對象的生命周期的完整,因為它還會有feature,會在具體的feature對象中保存id信息和其它擴展信息,詳見下面的PubSubFeature類的解析。

C. Hiview service

  1. typedef struct { 
  2.     INHERIT_IUNKNOWN;     
  3.     void (*Output)(IUnknown *iUnknown, int16 msgId, uint16 type); 
  4. } HiviewInterface; 
  5.  
  6. typedef struct { 
  7.     INHERIT_SERVICE; 
  8.     INHERIT_IUNKNOWNENTRY(HiviewInterface); 
  9.     Identity identity; 
  10. } HiviewService;  

 Hiview service除了繼承自Service類實現(xiàn)service的生命周期函數(shù)之外,還繼承了HiviewInterface,這個HiviewInterface又繼承了最原始的IUnknown接口類(INHERIT_IUNKNOWN)。通過這種多繼承機制,既實現(xiàn)了服務所需的生命周期,又具備了類似feature所提供的部分接口功能(Hiview service實際上又不帶feature)。

詳情見下面對IUnknown類的分析。

identity則是Hiview service對象的身份信息,同樣包括了: serviceId/featureId/queueId三個信息。

4.6 Feature類及其子類

  1. struct Feature { 
  2.     const char *(*GetName)(Feature *feature);                         //獲取feature的名字 
  3.     void (*OnInitialize)(Feature *feature, Service *parent, Identity identity);  //feature 的初始化 
  4.     void (*OnStop)(Feature *feature, Identity identity);                   //停止對外提供feature功能 
  5.     BOOL (*OnMessage)(Feature *feature, Request *request);             //對本feature的消息處理 
  6. }; 

 Feature類是所有feature類的父類,也是聲明了四個函數(shù)指針,這是每一個feature都必須要實現(xiàn)的生命周期函數(shù),見上面的注釋。

每一個具體的feature類都繼承自這個Feature類,然后擴展自己獨特的功能。

下面是Hi3861的Broadcast service 提供的feature類及Impl類的定義:

A: PubSubFeature g_broadcastFeature

  1. typedef struct PubSubFeature PubSubFeature; 
  2. struct PubSubFeature { 
  3.     INHERIT_FEATURE;   //繼承 Feature 類 
  4.     Relation *(*GetRelation)(PubSubFeature *feature, const Topic *topic); 
  5.     MutexId mutex; 
  6.     Relation relations; 
  7.     Identity identity; 
  8. }; 

 PubSubFeature 本尊,它被FeatureImpl 對象以及下面的PubSubImplement 對象引用。

FeatureImpl 對象又會被記錄在 ServiceImpl 的Features Vector向量里,獲得一個Fid,連同Sid/Qid一起記錄在PubSubFeature 的identity里。

PubSubFeature 還提供一個雙向鏈表結構的Relation,以及基于這個雙向鏈表結構的查找節(jié)點的函數(shù)GetRelation(),這個結構及其作用,我后面再另寫文章詳細分析。

B: PubSubImplement g_pubSubImplement

  1. typedef struct PubSubInterface PubSubInterface; 
  2. struct PubSubInterface { 
  3.     INHERIT_IUNKNOWN; 
  4.     Subscriber subscriber; 
  5.     Provider provider; 
  6. }; 
  7.  
  8. typedef struct PubSubImplement { 
  9.     INHERIT_IUNKNOWNENTRY(PubSubInterface); 
  10.     PubSubFeature *feature; 
  11. } PubSubImplement; 

 PubSubImplement 對象會引用上面的PubSubFeature對象,記錄在這里的PubSubFeature *feature上。

PubSubImplement 還繼承了PubSubInterface,實現(xiàn)了Subscriber 和Provider的功能。

它們的關系,見本文最上面的展開圖。

這個PubSubFeature 和PubSubImplement 深究下去就有點復雜了,它們是SOA(面向服務的架構)的具體實現(xiàn):

  • Provider:服務的提供者,為系統(tǒng)提供能力(對外接口)。
  • Consumer:服務的消費者,調用服務提供的功能(對外接口)。
  • Samgr:作為中介者,管理Provider提供的能力,同時幫助Consumer發(fā)現(xiàn)Provider的能力。

如下是官方readme上畫的架構圖。

這里我就先不做進一步詳細的分析了,后面會結合broadcast_example.c示例程序來做分析和驗證,再單獨寫一篇文章來做總結。

4.7 IUnknown 接口類及其相關定義

首先需要理解,C語言的struct本質上與C++中的class是一樣的,都是一塊存儲區(qū)域,里面有數(shù)據(jù)和對數(shù)據(jù)的操作。C++通過“:”關鍵字來標記繼承關系,如Aa繼承自A表示為“class Aa : public A”,而C語言直接是struct Aa內嵌套struct A來標記“繼承關系”:

  1. struct A { 
  2.     dataA; 
  3.     funcPtr* funcA; 
  4. struct Aa { 
  5.     struct A; 
  6.     dataAa; 
  7.     funcPtr* funcAa; 

 更具體的一些細節(jié),可以自行在網上搜索和學習。

接下來,我們仔細對比一下HivieService 和PubSubImplement,它們都分別通過INHERIT_IUNKNOWNENTRY() 這個關鍵字來分別繼承HiviewInterface和PubSubInterface,而這HiviewInterface和PubSubInterface又都通過INHERIT_IUNKNOWN來繼承IUnknown接口類。

下面我們就跟著Hi3861/foundation/distributedschedule/interfaces/innerkits/samgr_lite/samgr/iunknown.h中的定義去展開和理解一下這兩個宏(類)。

INHERIT_IUNKNOWN 宏定義是為了方便用C語言的形式“繼承”IUnknown接口類。

INHERIT_IUNKNOWNENTRY() 宏定義是為了方便用C語言的形式“繼承”【實現(xiàn)了IUnknown接口的】 IUnknownEntry接口類。

這兩個宏之間的關系,就是上面struct A和struct Aa之間的父類子類關系,換回struct 的形式,就是:

IUnknown 是父類,IUnknownEntry 是子類,子類是父類的一個implement。

按上面的定義把HiviewService類(或結構體)的定義徹底展開,就是如下的樣子:

把HiviewService的全局對象 g_hiviewService的初始化也按上面的形式展開,也會如下:

這樣一來,.iUnknown的地址、HiviewService類型、g_hiviewService對象的地址(引用/指針)之間的關系,就可以通過計算和類型轉換來互相獲取了,這就是下面三個宏的作用:

a. GET_IUNKNOWN(T)

定義在://foundation/distributedschedule/interfaces/innerkits/samgr_lite/samgr/iunknown.h

簡單理解為:從g_hiviewService對象中獲取其內部的.iUnknown對象的地址。

b. GET_OFFSIZE(T, member)

c. GET_OBJECT(Ptr, T, member)

這兩個定義在://foundation/distributedschedule/interfaces/innerkits/samgr_lite/samgr/common.h

簡單理解為:從.iUnknown父類對象下轉換得到子類HiviewInterface對象或者g_hiviewService對象的地址。

如本文開頭的第一張展開圖所示,BroadcastImpl和HiviewImpl都有自己的 IUnknown* defaultApi,分別是通過GET_IUNKNOWN(g_pubSubImplement) 和GET_IUNKNOWN(g_hiviewService)來得到的,得到了.iUnknown的地址,也就是得到了(*QueryInterface)/(*AddRef)/(*Release)這三個defaultApi的地址,就可以使用它們了,實際只直接使用(*QueryInterface)這個API,它的作用是“Queries the subclass object of the IUnknown interface of a specified version”

查詢/獲取指定的版本的IUnknown接口的子類對象(同時增加對該對象的引用次數(shù)),調用者通過這個子類對象就可以調用子類中定義的其它接口了。

對于上面的g_hiviewService例子來說,調用QueryInterface接口的例子在hiview_service.c 的HiviewSendMessage() 里,它返回的實際上就是g_hiviewService 這個service對象內部的一個區(qū)域的起始地址,這個區(qū)域就是HiviewInterface這個類的對象,同時增加了對這個對象的引用次數(shù),之后,就可以通過這個對象來調用HiviewInterface所定義的全部API了(這里主要是Output函數(shù))。

4.8 其它類/結構體

samgr子系統(tǒng)中還有其他的一些很重要的類或結構體,比如Request/Response/Exchange 等等,這里就先不進一步展開了,以后應該還會繼續(xù)補充完整的,或者在接下來的流程分析中按需進行分解,也請各位自行做一下理解。

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區(qū)

https://harmonyos.51cto.com

 

責任編輯:jianghua 來源: 鴻蒙社區(qū)
相關推薦

2021-06-03 14:21:44

鴻蒙HarmonyOS應用

2021-06-18 10:02:10

鴻蒙HarmonyOS應用

2021-06-18 15:23:59

鴻蒙HarmonyOS應用

2021-07-08 16:16:59

鴻蒙HarmonyOS應用

2021-07-05 09:35:36

鴻蒙HarmonyOS應用

2021-07-07 09:45:20

鴻蒙HarmonyOS應用

2021-07-12 09:50:39

鴻蒙HarmonyOS應用

2021-04-30 09:43:27

鴻蒙HarmonyOS應用

2022-03-15 15:00:59

Hi3861Pin接口鴻蒙

2020-10-16 09:50:37

Hi3861WiFi熱點

2023-05-26 16:07:14

Hi3861Wifi模塊

2022-03-07 15:05:58

HTTPHi3861數(shù)據(jù)解析

2020-11-03 11:39:22

wifi小車

2020-10-30 09:41:44

鴻蒙Hi3861WiFi小車

2020-10-14 09:41:02

Hi3861GPIO點燈

2021-07-01 14:21:58

鴻蒙HarmonyOS應用

2022-05-30 15:21:27

Hi3861TCP通信

2020-11-02 12:07:11

鴻蒙 GPIO

2022-09-13 15:54:41

samgr鴻蒙

2020-10-12 09:36:04

鴻蒙
點贊
收藏

51CTO技術棧公眾號