偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

[[404768]]

想了解更多內(nèi)容,請(qǐng)?jiān)L問:

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

https://harmonyos.51cto.com

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

4 結(jié)構(gòu)體的分解

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.         }; 

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

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

A: SamgrLite vtbl;

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

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

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

B: MutexId mutex;

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

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

類似的還有內(nèi)存、隊(duì)列、線程、timer的相關(guān)操作,代碼見:

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

理論上,全局對(duì)象g_samgrImpl初始化(init)時(shí)就會(huì)生成一個(gè)mutex,且只要g_samgrImpl沒有重新初始化,這個(gè)mutex就應(yīng)該是不變的,Hi3861平臺(tái)上我看到的也確實(shí)如此。

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

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

C: BootStatus status;

系統(tǒng)的啟動(dòng)階段狀態(tài)標(biāo)記。

Hi3861平臺(tái)上電啟動(dòng)到 system_init.c 的

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

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

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

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

D: Vector services;

g_samgrImpl 初始化時(shí):

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

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

其中:

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

Samgr通過這個(gè)Vector來管理所有注冊(cè)進(jìn)來的service(實(shí)際上管理的是serviceImpl對(duì)象,通過serviceImpl來關(guān)聯(lián)具體的service和service對(duì)應(yīng)的feature)。

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

對(duì)Vector的操作,全部定義在:

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

里面了,需要仔細(xì)閱讀分析,去理解相關(guān)操作。

下面是幾處要點(diǎn):

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

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

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

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

Hi3861平臺(tái)啟動(dòng)到 system_init.c 的最后一步時(shí):

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

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

請(qǐng)自行查看 TaskConfig的定義。

這里需要關(guān)注的是 SHARED_TASK 這個(gè)標(biāo)記,在samgr的 AddTaskPool()這一步時(shí):

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

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

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

我在代碼里全局搜索了一下“SHARED_TASK”關(guān)鍵字,得到如下結(jié)果:

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

不是SHARED_TASK的service則有自己獨(dú)立的Queue和taskPool,不會(huì)直接記錄在g_samgrImpl.sharedPool[]里,而是記錄在各自service的serviceImpl對(duì)象的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對(duì)象的指針,并不直接記錄和管理service、feature對(duì)象本身。service在向samgr注冊(cè)自己時(shí),samgr會(huì)首先生成一個(gè)ServiceImpl對(duì)象,將service對(duì)象的指針記錄在ServiceImpl的Service* service里,而ServiceImpl對(duì)象本身的指針,則記錄在g_samgrImpl.services.data[i] 中,這樣就建立了g_samgrImpl 到具體service的聯(lián)系,見本文上面的展開圖。

A: Service* service;    

指向當(dāng)前ServiceImpl對(duì)象所對(duì)應(yīng)的具體的service對(duì)象,這些具體的service對(duì)象都是Service類的子類對(duì)象。

B: IUnknown* defaultApi;

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

詳情見下面對(duì)IUnknown的分析。

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

C: TaskPool* taskPool;

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

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

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

D: Vector features;

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

一個(gè)service沒有feature時(shí),features Vector就保持初始化的樣子,對(duì)應(yīng)的features.data 是NULL。

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

E: int16 serviceId;

當(dāng)前的ServiceImpl 對(duì)象指針保存在g_samgrImpl.services vector內(nèi)的data[x]上的這個(gè) x 序號(hào),就作為當(dāng)前service的ID,保存在這里。這個(gè)serviceId也可能同時(shí)保存在具體的service對(duì)象的Identity 結(jié)構(gòu)體里。

F: uint8 inited;

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

G: Operations ops;

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

4.4 FeatureImpl類

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

 FeatureImpl 類看起來相對(duì)簡單,直接是一個(gè)Feature指針(A)指向?qū)?yīng)的具體的feature對(duì)象。

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

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

更多詳情見下面對(duì)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 任務(wù)運(yùn)行的配置 

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

每一個(gè)具體的服務(wù)類都繼承自這個(gè)Service類,然后可以擴(kuò)展自己獨(dú)特的功能。

下面分別看一下Hi3861默認(rèn)的三個(gè)具體的服務(wù)。

A: Bootstrap service

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

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

  • Identity identity

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

serviceId:Bootstrap service 對(duì)應(yīng)的 serviceImpl對(duì)象,在g_samgrImpl.services這個(gè)Vector.data[]中存放位置 的index,這里值為0.

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

queueId: Bootstrap service啟動(dòng)時(shí),samgr會(huì)為其創(chuàng)建消息隊(duì)列,這就是消息隊(duì)列的ID,是一串?dāng)?shù)字。

  • uint8 flag

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

B. Broadcast service

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

 Broadcast service僅僅直接繼承了Service類,確保它的service對(duì)象的生命周期的完整,因?yàn)樗€會(huì)有feature,會(huì)在具體的feature對(duì)象中保存id信息和其它擴(kuò)展信息,詳見下面的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類實(shí)現(xiàn)service的生命周期函數(shù)之外,還繼承了HiviewInterface,這個(gè)HiviewInterface又繼承了最原始的IUnknown接口類(INHERIT_IUNKNOWN)。通過這種多繼承機(jī)制,既實(shí)現(xiàn)了服務(wù)所需的生命周期,又具備了類似feature所提供的部分接口功能(Hiview service實(shí)際上又不帶feature)。

詳情見下面對(duì)IUnknown類的分析。

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

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);                   //停止對(duì)外提供feature功能 
  5.     BOOL (*OnMessage)(Feature *feature, Request *request);             //對(duì)本feature的消息處理 
  6. }; 

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

每一個(gè)具體的feature類都繼承自這個(gè)Feature類,然后擴(kuò)展自己獨(dú)特的功能。

下面是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 對(duì)象以及下面的PubSubImplement 對(duì)象引用。

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

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

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 對(duì)象會(huì)引用上面的PubSubFeature對(duì)象,記錄在這里的PubSubFeature *feature上。

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

它們的關(guān)系,見本文最上面的展開圖。

這個(gè)PubSubFeature 和PubSubImplement 深究下去就有點(diǎn)復(fù)雜了,它們是SOA(面向服務(wù)的架構(gòu))的具體實(shí)現(xiàn):

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

如下是官方readme上畫的架構(gòu)圖。

這里我就先不做進(jìn)一步詳細(xì)的分析了,后面會(huì)結(jié)合broadcast_example.c示例程序來做分析和驗(yàn)證,再單獨(dú)寫一篇文章來做總結(jié)。

4.7 IUnknown 接口類及其相關(guān)定義

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

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

 更具體的一些細(xì)節(jié),可以自行在網(wǎng)上搜索和學(xué)習(xí)。

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

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

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

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

這兩個(gè)宏之間的關(guān)系,就是上面struct A和struct Aa之間的父類子類關(guān)系,換回struct 的形式,就是:

IUnknown 是父類,IUnknownEntry 是子類,子類是父類的一個(gè)implement。

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

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

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

a. GET_IUNKNOWN(T)

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

簡單理解為:從g_hiviewService對(duì)象中獲取其內(nèi)部的.iUnknown對(duì)象的地址。

b. GET_OFFSIZE(T, member)

c. GET_OBJECT(Ptr, T, member)

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

簡單理解為:從.iUnknown父類對(duì)象下轉(zhuǎn)換得到子類HiviewInterface對(duì)象或者g_hiviewService對(duì)象的地址。

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

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

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

4.8 其它類/結(jié)構(gòu)體

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

想了解更多內(nèi)容,請(qǐng)?jiān)L問:

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

https://harmonyos.51cto.com

 

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

2021-06-03 14:21:44

鴻蒙HarmonyOS應(yīng)用

2021-06-18 10:02:10

鴻蒙HarmonyOS應(yīng)用

2021-06-18 15:23:59

鴻蒙HarmonyOS應(yīng)用

2021-07-08 16:16:59

鴻蒙HarmonyOS應(yīng)用

2021-07-07 09:45:20

鴻蒙HarmonyOS應(yīng)用

2021-07-05 09:35:36

鴻蒙HarmonyOS應(yīng)用

2021-07-12 09:50:39

鴻蒙HarmonyOS應(yīng)用

2022-03-15 15:00:59

Hi3861Pin接口鴻蒙

2020-10-16 09:50:37

Hi3861WiFi熱點(diǎn)

2021-04-30 09:43:27

鴻蒙HarmonyOS應(yīng)用

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點(diǎn)燈

2021-07-01 14:21:58

鴻蒙HarmonyOS應(yīng)用

2022-05-30 15:21:27

Hi3861TCP通信

2020-11-02 12:07:11

鴻蒙 GPIO

2020-10-28 10:03:43

Hi3861 GPIO點(diǎn)燈按鍵

2021-09-09 10:06:09

鴻蒙HarmonyOS應(yīng)用
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)