Hi3861的SAMGR--系統(tǒng)服務(wù)框架子系統(tǒng)-3
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
接前文《Hi3861的SAMGR--系統(tǒng)服務(wù)框架子系統(tǒng)-1》《Hi3861的SAMGR--系統(tǒng)服務(wù)框架子系統(tǒng)-2》
刪除《系統(tǒng)服務(wù)框架子系統(tǒng)-1》的 “3.大概流程” 這一小節(jié),由本文進(jìn)行替換。
samgr的展開圖和Hi3861開機(jī)部分的log,一并打包到附件,請看圖和log,結(jié)合代碼,理解本文。
3. 詳細(xì)流程分析
Hi3861平臺在啟動到HOS_SystemInit()時,
- void HOS_SystemInit(void)
- {
- ......
- printf("[system_init] [7-4]: SYS_INIT(service)=====================\n");
- SYS_INIT(service);
- printf("[system_init] [7-5]: SYS_INIT(feature)=====================\n");
- SYS_INIT(feature);
- ......
- printf("[system_init] [7-7]: SAMGR_Bootstrap()=====================\n");
- SAMGR_Bootstrap();
- }
會分別通過上面三步來:
- A. 注冊系統(tǒng)服務(wù)(service)
- B. 注冊系統(tǒng)服務(wù)提供的功能(feature)
- C. 通過samgr啟動并開始管理系統(tǒng)服務(wù)和功能
下面我們就結(jié)合上面提供的samgr展開圖,看看這三步具體都做了哪些工作。
A. 注冊系統(tǒng)服務(wù)(service)
- [system_init] [7-4]: SYS_INIT(service)=====================
- [bootstrap_service] SYS_SERVICE_INIT(Init): Bootstrap
- [samgr_lite] SAMGR_GetInstance(mutex=NULL): NO SAMGR instance, Init() to create ONE
- [samgr_lite] Init. g_samgrImpl
- [samgr_lite] Init. mutex[956036]. sharedPool[0-8] reset to 0. status=0[BOOT_SYS]
- [samgr_lite] SAMGR_GetInstance(mutex=956036)
- [samgr_lite] RegisterService(Name:Bootstrap)->Sid[0]
- [broadcast_service] SYS_SERVICE_INIT(Init): Broadcast
- [samgr_lite] RegisterService(Name:Broadcast)->Sid[1]
- [hiview_service] SYS_SERVICE_INIT(Init): hiview
- [samgr_lite] RegisterService(Name:hiview)->Sid[2]
- [samgr_lite] RegisterFeatureApi(serviceName[hiview], feature[(null)])
- [hiview_service] Init.InitHiviewComponent.
從上述og看,會首先注冊三個系統(tǒng)服務(wù)。
第一個注冊的系統(tǒng)服務(wù)是Bootstrap:
- SAMGR_GetInstance()->RegisterService((Service *)&bootstrap);
復(fù)制這個時候samgr還沒有實(shí)例,所以需要先通過Init()初始化samgr的全局實(shí)例g_samgrImpl:

然后才能調(diào)用RegisterService((Service *)&bootstrap)來向g_samgrImpl注冊bootstrap服務(wù),下圖是RegisterService()函數(shù)的代碼片段截圖:

調(diào)用SAMGR_CreateServiceImpl()為bootstrap創(chuàng)建一個ServiceImpl對象,并把bootstrap service對象與ServiceImpl.service關(guān)聯(lián)起來,同時也為ServiceImpl.features創(chuàng)建一個默認(rèn)的空的向量,以便下一步為service關(guān)聯(lián)對應(yīng)的feature。
再通過VECTOR_Add()操作,將ServiceImpl對象的引用加入g_samgrImpl.services向量中,并返回它在向量中的位置[0],以此作為bootstrap 的ServiceID[0]。
接下來注冊的第二個服務(wù)broadcast和第三個服務(wù)hiview,就可以直接通過RegisterService((Service *)Xxx)記錄進(jìn)g_samgrImpl.services向量里了,Sid分別是[1]/[2]。服務(wù)的注冊過程與上面bootstrap的過程一樣。
B. 注冊系統(tǒng)服務(wù)提供的功能(feature)
- [system_init] [7-5]: SYS_INIT(feature)=====================
- [pub_sub_feature] Init. SYS_FEATURE_INIT(Init) g_broadcastFeature: Provider and subscriber
- [samgr_lite] RegisterFeature(serviceName:Broadcast, featureName:Provider and subscriber)->Fid[0]
- [pub_sub_implement] BCE_CreateInstance: set g_pubSubImplement.feature = &g_broadcastFeature
- [samgr_lite] RegisterFeatureApi(serviceName[Broadcast], feature[Provider and subscriber])
接下來注冊broadcast service的feature:PUB_SUB_FEATURE。
feature的注冊和運(yùn)行需要依賴于對應(yīng)的service,一個service可以有0個、1個或多個feature。

這里通過調(diào)用RegisterFeature(service, feature)來注冊feature并與對應(yīng)的service關(guān)聯(lián)在一起,下圖是RegisterFeature() 函數(shù)的代碼片段截圖:

g_samgrImpl首先通過service name找到上一步登記在冊的對應(yīng)的serviceImpl對象,將其與feature對象一起作為參數(shù),送入DEFAULT_AddFeature()。

DEFAULT_AddFeature()里面,也會通過FEATURE_CreateInstance()先生成一個FeatureImpl對象,再通過VECTOR_Add()操作,將FeatureImpl對象的引用加入到 ServiceImpl.features這個向量中去,并返回它在向量中的位置[0],以此作為PUB_SUB_FEATURE的featureId[0],這就完成了feature與service的關(guān)聯(lián),也就完成了feature的注冊工作。
上面A和B兩步,就已經(jīng)完成了前面的samgr展開圖中的大部分工作(除了與創(chuàng)建queue/taskPool相關(guān)部分),至此,samgr與service/feature之間的樹形關(guān)系已經(jīng)基本上成型了,但都還是靜態(tài)關(guān)系:g_samgrImpl的services向量,已經(jīng)記錄了這一啟動階段注冊進(jìn)來的所有系統(tǒng)服務(wù)的ServiceImpl ,而每個ServiceImpl的features向量,又記錄了注冊進(jìn)來的與其對應(yīng)的所有features的FeatureImpl對象。【看samgr的展開圖】
這里記錄的serviceName/serviceID(Sid) 和featureName/featureID(Fid) 都是非常重要的信息,在接下來的系統(tǒng)啟動和運(yùn)行中,samgr可以通過它們來找到對應(yīng)的ServiceImpl/FeatureImpl對象,并提供相應(yīng)的服務(wù)/功能。
C. 通過samgr啟動并開始管理系統(tǒng)服務(wù)和功能
- [system_init] [7-7]: SAMGR_Bootstrap()=====================
- [samgr_lite] SAMGR_Bootstrap(status[1:BOOT_SYS_WAIT]). Begin: size=3
- InitializeAllServices: unInited services: size=3
- ----------------------------------------------------
- Add service: Bootstrap to TaskPool: 0x0...
- TaskPool: 0xfa488...
- Qid: 956424...
- InitializeSingleService(Bootstrap): SAMGR_SendSharedDirectRequest(handler[HandleInitRequest])
- [message] SAMGR_SendSharedDirectRequest: Put Exchange into Qid:[956424],type[4], request.msgId[0]+msgValue[0]:
- ----------------------------------------------------
- Add service: Broadcast to TaskPool: 0x0...
- TaskPool: 0xfaaf8...
- Qid: 956468...
- InitializeSingleService(Broadcast): SAMGR_SendSharedDirectRequest(handler[HandleInitRequest])
- [message] SAMGR_SendSharedDirectRequest: Put Exchange into Qid:[956468],type[4], request.msgId[0]+msgValue[0]:
- ----------------------------------------------------
- Add service: hiview to TaskPool: 0x0...
- TaskPool: 0xfacb8...
- Qid: 956512...
- InitializeSingleService(hiview): SAMGR_SendSharedDirectRequest(handler[HandleInitRequest])
- [message] SAMGR_SendSharedDirectRequest: Put Exchange into Qid:[956512],type[4], request.msgId[0]+msgValue[0]:
- ----------------------------------------------------
- [task_manager] SAMGR_StartTaskPool:
- CreateTask[Bootstrap(Tid: 0xe87c0), size(2048), Prio(25)]-OK!
- [task_manager] SAMGR_StartTaskPool:
- CreateTask[Broadcast(Tid: 0xe875c), size(2048), Prio(32)]-OK!
- [task_manager] SAMGR_StartTaskPool:
- CreateTask[hiview(Tid: 0xe8824), size(2048), Prio(24)]-OK!
- ----------------------------------------------------
- [samgr_lite] InitCompleted: services[3-0] inited, OK! END!
- [samgr_lite] SAMGR_Bootstrap. End.
進(jìn)入SAMGR_Bootstrap() 函數(shù)中:
首先創(chuàng)建一個空的臨時向量Vector initServices,用于收集還沒有初始化的服務(wù)。
接著遍歷g_samgrImpl.services向量中登記在冊的所有serviceImpl對象,查看它們的inited標(biāo)記是否為SVC_INIT,是則表示對應(yīng)的service需要做初始化,將其加入到臨時的向量表中;inited標(biāo)記如果不是SVC_INIT,則表示對應(yīng)的service已經(jīng)初始化過了,不需要再次初始化,也就不用加入到臨時的向量表中。
接著通過InitializeAllServices(&initServices)把記錄在initServices臨時向量中的serviceImpl列表依次初始化一遍,也就是根據(jù)具體的service提供的TaskConfig參數(shù),創(chuàng)建Queue和TaskPool這些運(yùn)行環(huán)境。通過AddTaskPool()及其參數(shù),為不同的service創(chuàng)建不同的TaskPool,這里有三種task類型,我們重點(diǎn)關(guān)注一下“SHARED_TASK”這種,詳情見前文《系統(tǒng)服務(wù)框架子系統(tǒng)-2》中,對SHARED_TASK類型的分析。

跑完AddTaskPool()之后,各個service都有了自己的QueueID/TaskPool資源了,InitializeSingleService(serviceImpl)就會發(fā)送SharedDirectRequest(消息類型type=4,即MSG_DIRECT)到各自service的Queue中,等待消息被處理。
接下來就是啟動service task了。
InitializeAllServices()內(nèi),依次為臨時向量initServices中的每個serviceImpl調(diào)用SAMGR_StartTaskPool (serviceImpl->taskPool, name); 來為service創(chuàng)建任務(wù)。
SAMGR_StartTaskPool() 代碼片段如下圖:

它創(chuàng)建和啟動service任務(wù)/線程,線程入口是TaskEntry()函數(shù),位于task_manager.c文件內(nèi)。

各個服務(wù)的TaskEntry線程,監(jiān)控著各自的消息隊(duì)列Queue,從中檢出消息,獲取Exchange封裝的數(shù)據(jù),根據(jù)里面的相關(guān)標(biāo)記調(diào)用相關(guān)的msg handler來進(jìn)行對應(yīng)的處理。
至此,SAMGR_Bootstrap()函數(shù)就跑完了,samgr將會與services進(jìn)入一種動態(tài)的互動關(guān)系中。
既然所有的service的消息隊(duì)列以及任務(wù)都已經(jīng)開始工作了,那上面InitializeSingleService(serviceImpl)發(fā)送的SharedDirectRequest(消息類型type=4,即MSG_DIRECT),就會被各自service的TaskEntry線程收到并進(jìn)行處理。
第一個service的線程啟動并進(jìn)入while(1)循環(huán),監(jiān)控消息隊(duì)列,獲取消息,通過Sid和Qid可以知道這是Broadcast服務(wù)首先對消息進(jìn)行處理。MSG_DIRECT消息處理的handle是HandleInitRequest(),這是samgr自己直接處理的初始化流程,這里將會調(diào)用Broadcast服務(wù)的生命周期函數(shù)之一的Initialize() 對服務(wù)進(jìn)行初始化,Broadcast service下存在feature,也會同時調(diào)用feature的OnInitialize對feature進(jìn)行初始化,如下log所示:
- TaskEntry(Qid:956468) into while(1) wait for MSG from queue....
- TaskEntry(Qid:956468) Recv MSG:
- request.msgId[0]+msgValue[0] -->> Sid[1],Fid[-1],Qid[0]
- type[4]:MSG_DIRECT/DirectRequest by handler
- [samgr_lite] HandleInitRequest. to Init service:[Broadcast]Sid[1] and its features, updating Qid-->>
- [broadcast_service] Initialize.[Sid:1, Fid:-1, Qid:956468]
- [pub_sub_feature] OnInitialize(featureName[Provider and subscriber], [Sid:1, Fid:0, Qid:956468])
- -->>updated Qid[956468]
- [samgr_lite] InitCompleted: services[3-0] inited, OK! END!
第二個service的線程啟動并進(jìn)入while(1)循環(huán),監(jiān)控消息隊(duì)列,獲取消息,通過Sid和Qid可以知道這是Bootstrap服務(wù)要對消息進(jìn)行處理。仍然是MSG_DIRECT消息處理,samgr的HandleInitRequest()的初始化流程,調(diào)用Bootstrap服務(wù)的生命周期函數(shù)之一的Initialize() 對服務(wù)進(jìn)行初始化,沒有feature,如下log:
- TaskEntry(Qid:956424) into while(1) wait for MSG from queue....
- TaskEntry(Qid:956424) Recv MSG:
- request.msgId[0]+msgValue[0] -->> Sid[0],Fid[-1],Qid[0]
- type[4]:MSG_DIRECT/DirectRequest by handler
- [samgr_lite] HandleInitRequest. to Init service:[Bootstrap]Sid[0] and its features, updating Qid-->>
- [bootstrap_service] Initialize.[Sid:0, Fid:-1, Qid:956424]
- -->>updated Qid[956424]
- [samgr_lite] InitCompleted: services[3-2] inited, OK! END!
第三個service的線程啟動并進(jìn)入while(1)循環(huán),監(jiān)控消息隊(duì)列,獲取消息,通過Sid和Qid可以知道這是hiview服務(wù)要對消息進(jìn)行處理。仍然是MSG_DIRECT消息處理,samgr的HandleInitRequest()的初始化流程,調(diào)用hiview服務(wù)的生命周期函數(shù)之一的Initialize() 對服務(wù)進(jìn)行初始化,沒有feature,如下log:
- TaskEntry(Qid:956512) into while(1) wait for MSG from queue....
- TaskEntry(Qid:956512) Recv MSG:
- request.msgId[0]+msgValue[0] -->> Sid[2],Fid[-1],Qid[0]
- type[4]:MSG_DIRECT/DirectRequest by handler
- [samgr_lite] HandleInitRequest. to Init service:[hiview]Sid[2] and its features, updating Qid-->>
- [hiview_service] Initialize([Sid:2, Fid:-1, Qid:956512])
- -->>updated Qid[956512]
- [samgr_lite] InitCompleted: services[3-3] inited, OK! ...
從“InitCompleted: services[3-3] inited, OK!”這句log可以知道,三個系統(tǒng)服務(wù)(包括它們的feature)都已經(jīng)啟動完畢了,進(jìn)入InitCompleted()去看一下:

到這里,第一階段的系統(tǒng)服務(wù)就初始化完畢了,status也從1[BOOT_SYS_WAIT]轉(zhuǎn)變到2[BOOT_APP],接下來要進(jìn)入BOOT_APP階段了,這里會發(fā)送BOOT_SYS_COMPLETED消息給Bootstrap,讓Bootstrap調(diào)用MessageHandle()來處理該消息,去開啟APP service和feature的啟動:
- [samgr_lite] InitCompleted: status[1->2:BOOT_APP], all core system services Initialized!
- Going to SendBootRequest(msgId[0-BOOT_SYS_COMPLETED], msgValue:3)
- [samgr_lite] SendBootRequest(to Bootstrap(Sid:0, Qid:956424), request.msgId[0]+msgValue[3]) ->Handler: SAMGR_Bootstrap()
- [message] SAMGR_SendRequest: Put Exchange into Qid:[956424],type[1], request.msgId[0]+msgValue[3]:
上面的流程僅僅是啟動了用SYS_SERVICE_INIT()和SYS_FEATURE_INIT() 標(biāo)記的系統(tǒng)service和feature,而通過SYSEX_SERVICE_INIT/APP_SERVICE_INIT/ SYSEX_FEATURE_INIT/APP_FEATURE_INIT 標(biāo)記的APP service和feature(如在前面提到的示例程序samgr里定義的一部分service和feature),則會在上面這一步,通過發(fā)送BOOT_SYS_COMPLETED消息到Bootstrap的消息隊(duì)列中,讓Bootstrap調(diào)用MessageHandle()來處理該消息:
- TaskEntry(Qid:956424) Recv MSG:
- request.msgId[0]+msgValue[3] -->> Sid[0],Fid[-1],Qid[956512]
- type[1]:0MSG_NON/1CON/3SYNC/Request by service MessageHandle
- otstrap_service] MessageHandle(Bootstrap, request.msgId[0]+msgValue[3])
- case BOOT_SYS_COMPLETED[0]: flag[0]
- todo INIT_APP_CALL(service)/INIT_APP_CALL(feature)
Bootstrap的MessageHandle()消息處理函數(shù)通過調(diào)用INIT_APP_CALL(service)和INIT_APP_CALL(feature)來完成APP service和Feature的啟動,從而提供用戶定義的服務(wù)和功能。
Hi3861默認(rèn)是沒有APP service/feature的,可以打開samgr示例程序中的service_example和feature_example來進(jìn)行驗(yàn)證:
注冊service_example服務(wù)
- 注冊service_example服務(wù)
- [service_example] SYSEX_SERVICE_INIT(Init). example_service
- [samgr_lite] RegisterService(Name:example_service)->Sid[3]
- [samgr_lite] RegisterFeatureApi(serviceName[example_service], feature[(null)])
- 注冊service_example服務(wù)的example_feature
- [feature_example] SYSEX_FEATURE_INIT(Init). example_service:example_feature
- [samgr_lite] RegisterFeature(serviceName:example_service, featureName:example_feature)->Fid[0]
- [samgr_lite] RegisterFeatureApi(serviceName[example_service], feature[example_feature])
- -->>flag[1](0x01:LOAD_FLAG)
- [message] SAMGR_SendResponseByIdentity(Sid[0],Fid[-1],Qid[956424]): request.msgId[0]+msgValue[3]
- [message] SAMGR_SendResponse: Put Exchange into Qid:[956424],type[2], request.msgId[0]+msgValue[3]:
對service_example和feature_example,又跑一遍上面的ABC三步,創(chuàng)建example_service的queue、taskpool和task,service_example的線程啟動并進(jìn)入while(1)循環(huán),監(jiān)控消息隊(duì)列,獲取消息,處理消息,與上邊的三個系統(tǒng)服務(wù)基本沒什么差別了。
跑到下面這一步,APP service和feature都已經(jīng)全部啟動完畢,各個服務(wù)的task都在監(jiān)控自己的消息隊(duì)列,隨時處理收到的消息,系統(tǒng)進(jìn)入到了BOOT_DYNAMIC_WAIT 這個穩(wěn)定的狀態(tài)了。
我為了驗(yàn)證service_example和feature_example提供的服務(wù)和功能,增加了BOOT_DEBUG和BOOT_DEBUG_WAIT兩個狀態(tài),所以又多跑了下面的一部分流程,在現(xiàn)實(shí)的設(shè)備應(yīng)用環(huán)境中,也有可能會有各種情況下的類似的調(diào)用導(dǎo)致相關(guān)消息的發(fā)送和處理。
- TaskEntry(Qid:956424) Recv MSG:
- request.msgId[1]+msgValue[4] -->> Sid[0],Fid[-1],Qid[956424]
- type[2]:MSG_ACK/Response by SAMGR_Bootstrap
- response.data:"Bootstrap MessageHandle: BOOT_APP_COMPLETED"
- [samgr_lite] SAMGR_Bootstrap(status[5:BOOT_DYNAMIC_WAIT]). Begin: size=4
- [samgr_lite] InitCompleted: services[4-4] inited, OK! ...
- [samgr_lite] InitCompleted: status[5->6:BOOT_DEBUG], Going to run TEST_CASE
- Going to SendBootRequest(msgId[3-BOOT_TEST_RUN], msgValue:4)
- [samgr_lite] SendBootRequest(to Bootstrap(Sid:0, Qid:956424), request.msgId[3]+msgValue[4]) ->Handler: SAMGR_Bootstrap()
- [message] SAMGR_SendRequest: Put Exchange into Qid:[956424],type[1], request.msgId[3]+msgValue[4]:
- [samgr_lite] SAMGR_Bootstrap. End.
接下來的大段log就是開始跑 service_example.c 里的RunTestCase()和feature_example里的RunTestCase(),以及由此引發(fā)的各種消息的發(fā)送和處理了,通過這些測試用例,可以進(jìn)一步理解service/feature的工作流程和相關(guān)API的調(diào)用關(guān)系,感興趣的同學(xué)可以自行了解一下,這里就不進(jìn)一步分析了。
以后開發(fā)者開發(fā)自己的service/feature到實(shí)際應(yīng)用中去的時候,service/feature的生命周期和工作流程,將會與上面的流程保持一致。
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)