飞道的博客

鸿蒙OS开源代码精要解读之—— 系统服务框架子系统(服务启动)

369人阅读  评论(0)

鸿蒙OS开源代码精要解读之—— 系统服务框架子系统(服务启动)

作者介绍

中科创达OpenHarmony研究组

说明

中科创达OpenHarmony研究组第一时间对https://codechina.csdn.net/openharmony上开源的代码进行了详尽的代码研读和学习。为此,我们打算编写一系列篇幅中等,内容精炼的源码分析文章来引领大家更进一步的走进鸿蒙OS。随着对代码的了解,广大开发者想亲自动手参与的意愿和信心也会随之增强——这也是鸿蒙OS开源的意义所在。

本篇内容摘要:

Samgr模块提供了面向服务体系结构(SOA)的开发框架基础,提供了Servcie、Feature和Founction的基本模型,以及注册和发现功能。是鸿蒙Framework非常重要的部分。系统中基于Samgr开发了许多服务,如Broadcast service, Bootstrap Servcie等,用户也可以基于Samgr开发框架开发自己的Service。

本篇介绍了OpenHarmony服务按序注册和启动的流程。

主要结构体

 

关键成员说明:

1. struct TaskConfig:在注册Service时提供,描述了Servcie对应的task的优先级,栈等信息

2. struct TaskPool:初始化Service时生成

  • queueId:创建taskpool时生成,通过不同的queueId来向不同的Servcie task发送消息

3. struct Service:要注册的Servcie,用户需要实现如下四个函数:

  • GetName:返回Servcie名称
  • Initialize:Servcie初始化函数,一般是要保存Service初始化生成的身份信息用于后续收发消息
  • MessageHandle:信息处理函数
  • TaskConfig:返回Service对应的Task配置

4. struct Operations:记录Servcie的时间戳等信息

5. struct ServiceImpl:注册Servcie实际上注册的是ServiceImpl

  • Service *service:注册的Servcie
  • TaskPool *taskPool:初始化时申请的taskpool
  • Vector features:Service下的子feature
  • int16 serviceId:serviceId的值为servcie在Vector中的位置,这个值在加载时就已经确定。
  • uint8 inited:初始化标志

6. struct SamgrLiteImpl:全局只有一个SamgrLiteImpl g_samgrImpl。

  • BootStatus status:Service启动的状态,目前定义了以下状态值:
    • BOOT_SYS:将要启动系统Service
    • BOOT_SYS_WAIT:正在启动系统Service
    • BOOT_APP:将要启动APP Servcie
    • BOOT_APP_WAIT:正在启动APP Servcie
    • BOOT_DYNAMIC:将要启动Dynamic Servcie
    • BOOT_DYNAMIC_WAIT:正在启动Dynamic Service
  • Vector services:注册Servcie时将一个servcieImpl结构体追加到Vector末尾,用于后面的初始化

启动流程

下图Servcie注册的流程:

 

1. 系统service使用SYS_SERVICE_INIT,SYS_FEATURE_INIT,用户Service使用APP_SERVICE_INIT,APP_FEATURE_INIT来注册服务,对于M核,把服务的注册函数放到指定的段,在启动时找到此段调用所有的函数。对于A核这个宏定义使用了__attribute__(constructor)的特性,这个特性在在程序加载后,程序执行之前执行注册函数

 

2. 注册Servcie主要是把ServiceImpl追加到全局g_samgrImpl的成员services Vector,并根据Servcie在向量表中的序号来确定ServcieID。

 

3. 注册Feature主要是把FeatureImpl追加到对应服务的的features Vector,并根据Feature在向量表中的序号来确定FeatureID

下图是Service初始化流程:

 

4. 服务初始化的入口是SAMGR_Bootstrap(foundation/distributedschedule/services/samgr_lite/samgr/samgr_lite.c),主要实现以下功能:

a. 先更新全局g_samgrImpl的status:

而Status有如下的枚举:

那么更新的逻辑就是这样子了:

    如果status为BOOT_SYS == 0b,更新后是BOOT_SYS_WAIT == 1b;

    如果status为BOOT_APP == 10b,更新后是BOOT_APP_WAIT == 11b;

    如果status为BOOT_DYNAMIC == 100b,更新后是BOOT_DYNAMIC_WAIT == 101b;

    如果status为BOOT_SYS_WAIT == 1b; BOOT_APP_WAIT == 11b; BOOT_DYNAMIC_WAIT == 101b;更新后不变。

    g_samgrImpl的初始状态是BOOT_SYS,首次调用会更新为BOOT_SYS_WAIT

 

b. 收集全局g_samgrImpl->servcies Vector中还没有被初始化,状态为SVC_INIT的servcie,一起初始化

5. 为收集的每个Servcie创建TaskPool和创建消息队列。并拿到消息队列的句柄,以后向某个Servcie线程发送消息时就会发送给相应的队列。

6. 将函数HandleInitRequest发送到消息队列,这个函数将会在Service线程创建启动后,在Service对应的线程中执行。如果没有申请到队列,或者没有申请到taskpool,就在当前线程中执行初始化操作

7. 为每个申请到队列和taskpool的service创建和启动Task。

下图是Task的执行流程

Task循环执行以下内容:

    从消息队列中获取exchange并拿到ServiceImpl

    如果消息类型为MSG_ACK或者MSG_DIRECT,就执行exchange->handler函数,结合上一步,初始化时执行HandleInitRequest

    如果是其他类型(Request),则会调用Feature的 OnMessage或者Servcie的MessageHandle,然后再执行handler。

8. Service task启动后会从队列中获取到HandleInitRequest并执行,主要做了以下的工作:

  • 调用service的Initialize和feature OnInitialize函数,并将初始化过程中的ServcieID,FeatureID,和QueueID作为参数传出,service一般会保存该ID用于以后身份鉴别。
  • 更新Servcie的状态为SVC_IDLE
  • 检查全局g_samgrImpl的services vector是否还有未初始化的servcie(如图,pose >= size,则表示Service已经全部初始化完成),如果都完成了就更新status到下一个状态,并给Bootstrap服务发送消息告知此阶段初始化已完成

9. Bootstrap服务收到消息后就会加载下一阶段的程序。如果此时sys service已经完成,将会加载app

10. 用户Service使用APP_SERVICE_INIT,APP_FEATURE_INIT注册app service到全局g_samgrImpl的services vector中

11. SendBootRequest服务初始化入口SAMGR_Bootstrap作为handler传给bootstrap service,用户程序加载完成后bootstrap又会调用SAMGR_Bootstrap函数,返回第4步去初始化app servcie

12. 以此类推,最终按顺序完成sys service, app service, dynamic的初始化。


转载:https://blog.csdn.net/Innost/article/details/109023401
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场