Hi3861的SAMGR--系统服务框架子系统-3

系统
文章由鸿蒙社区产出,想要了解更多内容请前往:51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com

[[406193]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

接前文《Hi3861的SAMGR--系统服务框架子系统-1》《Hi3861的SAMGR--系统服务框架子系统-2》

删除《系统服务框架子系统-1》的 “3.大概流程” 这一小节,由本文进行替换。

samgr的展开图和Hi3861开机部分的log,一并打包到附件,请看图和log,结合代码,理解本文。

3. 详细流程分析

Hi3861平台在启动到HOS_SystemInit()时,

  1. void HOS_SystemInit(void) 
  2.     ...... 
  3.     printf("[system_init] [7-4]: SYS_INIT(service)=====================\n"); 
  4.     SYS_INIT(service); 
  5.     printf("[system_init] [7-5]: SYS_INIT(feature)=====================\n"); 
  6.     SYS_INIT(feature); 
  7.     ...... 
  8.     printf("[system_init] [7-7]: SAMGR_Bootstrap()=====================\n"); 
  9.     SAMGR_Bootstrap(); 

 会分别通过上面三步来:

  • A. 注册系统服务(service)
  • B. 注册系统服务提供的功能(feature)
  • C. 通过samgr启动并开始管理系统服务和功能

下面我们就结合上面提供的samgr展开图,看看这三步具体都做了哪些工作。

A. 注册系统服务(service)

  1. [system_init] [7-4]: SYS_INIT(service)===================== 
  2.  
  3. [bootstrap_service] SYS_SERVICE_INIT(Init): Bootstrap 
  4.  
  5. [samgr_lite] SAMGR_GetInstance(mutex=NULL): NO SAMGR instance, Init() to create ONE 
  6.  
  7. [samgr_lite] Init. g_samgrImpl 
  8.  
  9. [samgr_lite] Init. mutex[956036]. sharedPool[0-8] reset to 0. status=0[BOOT_SYS] 
  10.  
  11. [samgr_lite] SAMGR_GetInstance(mutex=956036) 
  12.  
  13. [samgr_lite] RegisterService(Name:Bootstrap)->Sid[0] 
  14.  
  15.   
  16.  
  17. [broadcast_service] SYS_SERVICE_INIT(Init): Broadcast 
  18.  
  19. [samgr_lite] RegisterService(Name:Broadcast)->Sid[1] 
  20.  
  21.   
  22.  
  23. [hiview_service] SYS_SERVICE_INIT(Init): hiview 
  24.  
  25. [samgr_lite] RegisterService(Name:hiview)->Sid[2] 
  26.  
  27. [samgr_lite] RegisterFeatureApi(serviceName[hiview], feature[(null)]) 
  28.  
  29. [hiview_service] Init.InitHiviewComponent. 

 从上述og看,会首先注册三个系统服务。

第一个注册的系统服务是Bootstrap:

  1. SAMGR_GetInstance()->RegisterService((Service *)&bootstrap); 

复制这个时候samgr还没有实例,所以需要先通过Init()初始化samgr的全局实例g_samgrImpl:

Hi3861的SAMGR--系统服务框架子系统-3-鸿蒙HarmonyOS技术社区

然后才能调用RegisterService((Service *)&bootstrap)来向g_samgrImpl注册bootstrap服务,下图是RegisterService()函数的代码片段截图:

Hi3861的SAMGR--系统服务框架子系统-3-鸿蒙HarmonyOS技术社区

调用SAMGR_CreateServiceImpl()为bootstrap创建一个ServiceImpl对象,并把bootstrap service对象与ServiceImpl.service关联起来,同时也为ServiceImpl.features创建一个默认的空的向量,以便下一步为service关联对应的feature。

再通过VECTOR_Add()操作,将ServiceImpl对象的引用加入g_samgrImpl.services向量中,并返回它在向量中的位置[0],以此作为bootstrap 的ServiceID[0]。

接下来注册的第二个服务broadcast和第三个服务hiview,就可以直接通过RegisterService((Service *)Xxx)记录进g_samgrImpl.services向量里了,Sid分别是[1]/[2]。服务的注册过程与上面bootstrap的过程一样。

B. 注册系统服务提供的功能(feature)

  1. [system_init] [7-5]: SYS_INIT(feature)===================== 
  2.  
  3. [pub_sub_feature] Init. SYS_FEATURE_INIT(Init) g_broadcastFeature: Provider and subscriber 
  4.  
  5. [samgr_lite] RegisterFeature(serviceName:Broadcast, featureName:Provider and subscriber)->Fid[0] 
  6.  
  7. [pub_sub_implement] BCE_CreateInstance: set g_pubSubImplement.feature = &g_broadcastFeature 
  8.  
  9. [samgr_lite] RegisterFeatureApi(serviceName[Broadcast], feature[Provider and subscriber]) 

接下来注册broadcast service的feature:PUB_SUB_FEATURE。

feature的注册和运行需要依赖于对应的service,一个service可以有0个、1个或多个feature。

Hi3861的SAMGR--系统服务框架子系统-3-鸿蒙HarmonyOS技术社区

这里通过调用RegisterFeature(service, feature)来注册feature并与对应的service关联在一起,下图是RegisterFeature() 函数的代码片段截图:

Hi3861的SAMGR--系统服务框架子系统-3-鸿蒙HarmonyOS技术社区

g_samgrImpl首先通过service name找到上一步登记在册的对应的serviceImpl对象,将其与feature对象一起作为参数,送入DEFAULT_AddFeature()。

Hi3861的SAMGR--系统服务框架子系统-3-鸿蒙HarmonyOS技术社区

DEFAULT_AddFeature()里面,也会通过FEATURE_CreateInstance()先生成一个FeatureImpl对象,再通过VECTOR_Add()操作,将FeatureImpl对象的引用加入到 ServiceImpl.features这个向量中去,并返回它在向量中的位置[0],以此作为PUB_SUB_FEATURE的featureId[0],这就完成了feature与service的关联,也就完成了feature的注册工作。

上面A和B两步,就已经完成了前面的samgr展开图中的大部分工作(除了与创建queue/taskPool相关部分),至此,samgr与service/feature之间的树形关系已经基本上成型了,但都还是静态关系:g_samgrImpl的services向量,已经记录了这一启动阶段注册进来的所有系统服务的ServiceImpl ,而每个ServiceImpl的features向量,又记录了注册进来的与其对应的所有features的FeatureImpl对象。【看samgr的展开图】

这里记录的serviceName/serviceID(Sid) 和featureName/featureID(Fid) 都是非常重要的信息,在接下来的系统启动和运行中,samgr可以通过它们来找到对应的ServiceImpl/FeatureImpl对象,并提供相应的服务/功能。

C. 通过samgr启动并开始管理系统服务和功能

  1. [system_init] [7-7]: SAMGR_Bootstrap()===================== 
  2.  
  3. [samgr_lite] SAMGR_Bootstrap(status[1:BOOT_SYS_WAIT]). Begin:   size=3 
  4.  
  5.         InitializeAllServices: unInited services: size=3 
  6.  
  7.         ---------------------------------------------------- 
  8.  
  9.         Add service: Bootstrap   to TaskPool: 0x0... 
  10.  
  11.                                 TaskPool: 0xfa488... 
  12.  
  13.                                     Qid: 956424... 
  14.  
  15.         InitializeSingleService(Bootstrap): SAMGR_SendSharedDirectRequest(handler[HandleInitRequest]) 
  16.  
  17. [message] SAMGR_SendSharedDirectRequest: Put Exchange into Qid:[956424],type[4], request.msgId[0]+msgValue[0]: 
  18.  
  19.         ---------------------------------------------------- 
  20.  
  21.         Add service: Broadcast   to TaskPool: 0x0... 
  22.  
  23.                                 TaskPool: 0xfaaf8... 
  24.  
  25.                                     Qid: 956468... 
  26.  
  27.         InitializeSingleService(Broadcast): SAMGR_SendSharedDirectRequest(handler[HandleInitRequest]) 
  28.  
  29. [message] SAMGR_SendSharedDirectRequest: Put Exchange into Qid:[956468],type[4], request.msgId[0]+msgValue[0]: 
  30.  
  31.         ---------------------------------------------------- 
  32.  
  33.         Add service: hiview      to TaskPool: 0x0... 
  34.  
  35.                                 TaskPool: 0xfacb8... 
  36.  
  37.                                     Qid: 956512... 
  38.  
  39.         InitializeSingleService(hiview): SAMGR_SendSharedDirectRequest(handler[HandleInitRequest]) 
  40.  
  41. [message] SAMGR_SendSharedDirectRequest: Put Exchange into Qid:[956512],type[4], request.msgId[0]+msgValue[0]: 
  42.  
  43.   
  44.  
  45. ---------------------------------------------------- 
  46.  
  47. [task_manager] SAMGR_StartTaskPool: 
  48.  
  49.         CreateTask[Bootstrap(Tid: 0xe87c0), size(2048), Prio(25)]-OK! 
  50.  
  51. [task_manager] SAMGR_StartTaskPool: 
  52.  
  53.         CreateTask[Broadcast(Tid: 0xe875c), size(2048), Prio(32)]-OK! 
  54.  
  55. [task_manager] SAMGR_StartTaskPool: 
  56.  
  57.         CreateTask[hiview(Tid: 0xe8824), size(2048), Prio(24)]-OK! 
  58.  
  59. ---------------------------------------------------- 
  60.  
  61. [samgr_lite] InitCompleted: services[3-0] inited, OK! END
  62.  
  63. [samgr_lite] SAMGR_Bootstrap. End

 进入SAMGR_Bootstrap() 函数中:

首先创建一个空的临时向量Vector initServices,用于收集还没有初始化的服务。

接着遍历g_samgrImpl.services向量中登记在册的所有serviceImpl对象,查看它们的inited标记是否为SVC_INIT,是则表示对应的service需要做初始化,将其加入到临时的向量表中;inited标记如果不是SVC_INIT,则表示对应的service已经初始化过了,不需要再次初始化,也就不用加入到临时的向量表中。

接着通过InitializeAllServices(&initServices)把记录在initServices临时向量中的serviceImpl列表依次初始化一遍,也就是根据具体的service提供的TaskConfig参数,创建Queue和TaskPool这些运行环境。通过AddTaskPool()及其参数,为不同的service创建不同的TaskPool,这里有三种task类型,我们重点关注一下“SHARED_TASK”这种,详情见前文《系统服务框架子系统-2》中,对SHARED_TASK类型的分析。

Hi3861的SAMGR--系统服务框架子系统-3-鸿蒙HarmonyOS技术社区

跑完AddTaskPool()之后,各个service都有了自己的QueueID/TaskPool资源了,InitializeSingleService(serviceImpl)就会发送SharedDirectRequest(消息类型type=4,即MSG_DIRECT)到各自service的Queue中,等待消息被处理。

接下来就是启动service task了。

InitializeAllServices()内,依次为临时向量initServices中的每个serviceImpl调用SAMGR_StartTaskPool (serviceImpl->taskPool, name); 来为service创建任务。

SAMGR_StartTaskPool() 代码片段如下图:

Hi3861的SAMGR--系统服务框架子系统-3-鸿蒙HarmonyOS技术社区

它创建和启动service任务/线程,线程入口是TaskEntry()函数,位于task_manager.c文件内。

Hi3861的SAMGR--系统服务框架子系统-3-鸿蒙HarmonyOS技术社区

各个服务的TaskEntry线程,监控着各自的消息队列Queue,从中检出消息,获取Exchange封装的数据,根据里面的相关标记调用相关的msg handler来进行对应的处理。

至此,SAMGR_Bootstrap()函数就跑完了,samgr将会与services进入一种动态的互动关系中。

既然所有的service的消息队列以及任务都已经开始工作了,那上面InitializeSingleService(serviceImpl)发送的SharedDirectRequest(消息类型type=4,即MSG_DIRECT),就会被各自service的TaskEntry线程收到并进行处理。

第一个service的线程启动并进入while(1)循环,监控消息队列,获取消息,通过Sid和Qid可以知道这是Broadcast服务首先对消息进行处理。MSG_DIRECT消息处理的handle是HandleInitRequest(),这是samgr自己直接处理的初始化流程,这里将会调用Broadcast服务的生命周期函数之一的Initialize() 对服务进行初始化,Broadcast service下存在feature,也会同时调用feature的OnInitialize对feature进行初始化,如下log所示:

  1.   TaskEntry(Qid:956468) into while(1) wait for MSG from queue.... 
  2.  
  3.         TaskEntry(Qid:956468) Recv MSG: 
  4.  
  5.                 request.msgId[0]+msgValue[0] -->> Sid[1],Fid[-1],Qid[0] 
  6.  
  7.                 type[4]:MSG_DIRECT/DirectRequest by handler 
  8.  
  9. [samgr_lite] HandleInitRequest. to Init service:[Broadcast]Sid[1] and its features, updating Qid-->> 
  10.  
  11. [broadcast_service] Initialize.[Sid:1, Fid:-1, Qid:956468] 
  12.  
  13. [pub_sub_feature] OnInitialize(featureName[Provider and subscriber], [Sid:1, Fid:0, Qid:956468]) 
  14.  
  15.         -->>updated Qid[956468] 
  16.  
  17. [samgr_lite] InitCompleted: services[3-0] inited, OK! END

第二个service的线程启动并进入while(1)循环,监控消息队列,获取消息,通过Sid和Qid可以知道这是Bootstrap服务要对消息进行处理。仍然是MSG_DIRECT消息处理,samgr的HandleInitRequest()的初始化流程,调用Bootstrap服务的生命周期函数之一的Initialize() 对服务进行初始化,没有feature,如下log:

  1.     TaskEntry(Qid:956424) into while(1) wait for MSG from queue.... 
  2.  
  3.         TaskEntry(Qid:956424) Recv MSG: 
  4.  
  5.                 request.msgId[0]+msgValue[0] -->> Sid[0],Fid[-1],Qid[0] 
  6.  
  7.                 type[4]:MSG_DIRECT/DirectRequest by handler 
  8.  
  9. [samgr_lite] HandleInitRequest. to Init service:[Bootstrap]Sid[0] and its features, updating Qid-->> 
  10.  
  11. [bootstrap_service] Initialize.[Sid:0, Fid:-1, Qid:956424] 
  12.  
  13.         -->>updated Qid[956424] 
  14.  
  15. [samgr_lite] InitCompleted: services[3-2] inited, OK! END

 第三个service的线程启动并进入while(1)循环,监控消息队列,获取消息,通过Sid和Qid可以知道这是hiview服务要对消息进行处理。仍然是MSG_DIRECT消息处理,samgr的HandleInitRequest()的初始化流程,调用hiview服务的生命周期函数之一的Initialize() 对服务进行初始化,没有feature,如下log:

  1.    TaskEntry(Qid:956512) into while(1) wait for MSG from queue.... 
  2.  
  3.         TaskEntry(Qid:956512) Recv MSG: 
  4.  
  5.                 request.msgId[0]+msgValue[0] -->> Sid[2],Fid[-1],Qid[0] 
  6.  
  7.                 type[4]:MSG_DIRECT/DirectRequest by handler 
  8.  
  9. [samgr_lite] HandleInitRequest. to Init service:[hiview]Sid[2] and its features, updating Qid-->> 
  10.  
  11. [hiview_service] Initialize([Sid:2, Fid:-1, Qid:956512]) 
  12.  
  13.         -->>updated Qid[956512] 
  14.  
  15. [samgr_lite] InitCompleted: services[3-3] inited, OK! ... 

 从“InitCompleted: services[3-3] inited, OK!”这句log可以知道,三个系统服务(包括它们的feature)都已经启动完毕了,进入InitCompleted()去看一下:

Hi3861的SAMGR--系统服务框架子系统-3-鸿蒙HarmonyOS技术社区

到这里,第一阶段的系统服务就初始化完毕了,status也从1[BOOT_SYS_WAIT]转变到2[BOOT_APP],接下来要进入BOOT_APP阶段了,这里会发送BOOT_SYS_COMPLETED消息给Bootstrap,让Bootstrap调用MessageHandle()来处理该消息,去开启APP service和feature的启动:

  1. [samgr_lite] InitCompleted: status[1->2:BOOT_APP], all core system services Initialized! 
  2.  
  3.         Going to SendBootRequest(msgId[0-BOOT_SYS_COMPLETED], msgValue:3) 
  4.  
  5. [samgr_lite] SendBootRequest(to Bootstrap(Sid:0, Qid:956424), request.msgId[0]+msgValue[3]) ->Handler: SAMGR_Bootstrap()      
  6.  
  7. [message] SAMGR_SendRequest: Put Exchange into Qid:[956424],type[1], request.msgId[0]+msgValue[3]: 

 上面的流程仅仅是启动了用SYS_SERVICE_INIT()和SYS_FEATURE_INIT() 标记的系统service和feature,而通过SYSEX_SERVICE_INIT/APP_SERVICE_INIT/ SYSEX_FEATURE_INIT/APP_FEATURE_INIT 标记的APP service和feature(如在前面提到的示例程序samgr里定义的一部分service和feature),则会在上面这一步,通过发送BOOT_SYS_COMPLETED消息到Bootstrap的消息队列中,让Bootstrap调用MessageHandle()来处理该消息:

  1. TaskEntry(Qid:956424) Recv MSG: 
  2.  
  3.              request.msgId[0]+msgValue[3] -->> Sid[0],Fid[-1],Qid[956512] 
  4.  
  5.              type[1]:0MSG_NON/1CON/3SYNC/Request by service MessageHandle 
  6.  
  7. otstrap_service] MessageHandle(Bootstrap, request.msgId[0]+msgValue[3]) 
  8.  
  9.      case BOOT_SYS_COMPLETED[0]: flag[0] 
  10.  
  11.      todo INIT_APP_CALL(service)/INIT_APP_CALL(feature) 

 Bootstrap的MessageHandle()消息处理函数通过调用INIT_APP_CALL(service)和INIT_APP_CALL(feature)来完成APP service和Feature的启动,从而提供用户定义的服务和功能。

Hi3861默认是没有APP service/feature的,可以打开samgr示例程序中的service_example和feature_example来进行验证:

注册service_example服务

  1. 注册service_example服务   
  2.  
  3. [service_example] SYSEX_SERVICE_INIT(Init). example_service 
  4.  
  5. [samgr_lite] RegisterService(Name:example_service)->Sid[3] 
  6.  
  7. [samgr_lite] RegisterFeatureApi(serviceName[example_service], feature[(null)]) 
  8.  
  9. 注册service_example服务的example_feature 
  10.  
  11. [feature_example] SYSEX_FEATURE_INIT(Init). example_service:example_feature 
  12.  
  13. [samgr_lite] RegisterFeature(serviceName:example_service, featureName:example_feature)->Fid[0] 
  14.  
  15. [samgr_lite] RegisterFeatureApi(serviceName[example_service], feature[example_feature]) 
  16.  
  17.                                 -->>flag[1](0x01:LOAD_FLAG) 
  18.  
  19. [message] SAMGR_SendResponseByIdentity(Sid[0],Fid[-1],Qid[956424]): request.msgId[0]+msgValue[3] 
  20.  
  21. [message] SAMGR_SendResponse: Put Exchange into Qid:[956424],type[2], request.msgId[0]+msgValue[3]: 

 对service_example和feature_example,又跑一遍上面的ABC三步,创建example_service的queue、taskpool和task,service_example的线程启动并进入while(1)循环,监控消息队列,获取消息,处理消息,与上边的三个系统服务基本没什么差别了。

跑到下面这一步,APP service和feature都已经全部启动完毕,各个服务的task都在监控自己的消息队列,随时处理收到的消息,系统进入到了BOOT_DYNAMIC_WAIT 这个稳定的状态了。

我为了验证service_example和feature_example提供的服务和功能,增加了BOOT_DEBUG和BOOT_DEBUG_WAIT两个状态,所以又多跑了下面的一部分流程,在现实的设备应用环境中,也有可能会有各种情况下的类似的调用导致相关消息的发送和处理。

  1.  TaskEntry(Qid:956424) Recv MSG: 
  2.  
  3.                 request.msgId[1]+msgValue[4] -->> Sid[0],Fid[-1],Qid[956424] 
  4.  
  5.                 type[2]:MSG_ACK/Response by SAMGR_Bootstrap 
  6.  
  7.                 response.data:"Bootstrap MessageHandle: BOOT_APP_COMPLETED" 
  8.  
  9. [samgr_lite] SAMGR_Bootstrap(status[5:BOOT_DYNAMIC_WAIT]). Begin:       size=4 
  10.  
  11. [samgr_lite] InitCompleted: services[4-4] inited, OK! ... 
  12.  
  13.   
  14.  
  15. [samgr_lite] InitCompleted: status[5->6:BOOT_DEBUG], Going to run TEST_CASE 
  16.  
  17.         Going to SendBootRequest(msgId[3-BOOT_TEST_RUN], msgValue:4) 
  18.  
  19. [samgr_lite] SendBootRequest(to Bootstrap(Sid:0, Qid:956424), request.msgId[3]+msgValue[4]) ->Handler: SAMGR_Bootstrap()      
  20.  
  21. [message] SAMGR_SendRequest: Put Exchange into Qid:[956424],type[1], request.msgId[3]+msgValue[4]: 
  22.  
  23. [samgr_lite] SAMGR_Bootstrap. End

 接下来的大段log就是开始跑 service_example.c 里的RunTestCase()和feature_example里的RunTestCase(),以及由此引发的各种消息的发送和处理了,通过这些测试用例,可以进一步理解service/feature的工作流程和相关API的调用关系,感兴趣的同学可以自行了解一下,这里就不进一步分析了。

以后开发者开发自己的service/feature到实际应用中去的时候,service/feature的生命周期和工作流程,将会与上面的流程保持一致。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-06-10 09:25:39

鸿蒙HarmonyOS应用

2021-06-03 14:21:44

鸿蒙HarmonyOS应用

2021-06-18 15:23:59

鸿蒙HarmonyOS应用

2021-07-05 09:35:36

鸿蒙HarmonyOS应用

2021-07-08 16:16:59

鸿蒙HarmonyOS应用

2021-07-07 09:45:20

鸿蒙HarmonyOS应用

2021-07-12 09:50:39

鸿蒙HarmonyOS应用

2021-04-30 09:43:27

鸿蒙HarmonyOS应用

2022-03-07 15:05:58

HTTPHi3861数据解析

2020-10-30 09:41:44

鸿蒙Hi3861WiFi小车

2022-03-15 15:00:59

Hi3861Pin接口鸿蒙

2020-10-16 09:50:37

Hi3861WiFi热点

2020-11-03 11:39:22

wifi小车

2020-10-27 10:08:19

Hi3861ADC驱动

2023-05-26 16:07:14

Hi3861Wifi模块

2022-05-30 15:21:27

Hi3861TCP通信

2020-11-02 12:07:11

鸿蒙 GPIO

2020-12-08 12:36:41

Hi3861 ADC驱动开发

2020-10-14 09:41:02

Hi3861GPIO点灯

2021-07-01 14:21:58

鸿蒙HarmonyOS应用
点赞
收藏

51CTO技术栈公众号