OpenHarmony移植案例与原理 - startup子系统之bootstrap_lite服务启动引导部件(2)

举报
zhushy 发表于 2022/02/22 11:33:47 2022/02/22
【摘要】 2.3 OHOS_SystemInit函数函数OHOS_SystemInit()定义在文件base\startup\bootstrap_lite\services\source\system_init.c,代码如下。调用宏函数MODULE_INIT、SYS_INIT和函数SAMGR_Bootstrap()进行初始化启动。void OHOS_SystemInit(void){ MODU...

2.3 OHOS_SystemInit函数

函数OHOS_SystemInit()定义在文件base\startup\bootstrap_lite\services\source\system_init.c,代码如下。调用宏函数MODULE_INIT、SYS_INIT和函数SAMGR_Bootstrap()进行初始化启动。

void OHOS_SystemInit(void)
{
    MODULE_INIT(bsp);
    MODULE_INIT(device);
    MODULE_INIT(core);
    SYS_INIT(service);
    SYS_INIT(feature);
    MODULE_INIT(run);
    SAMGR_Bootstrap();
}

我们详细分析下宏函数MODULE_INIT和SYS_INIT的源代码,这2个宏函数在文件base\startup\bootstrap_lite\services\source\core_main.h中定义,代码如下。这些宏函数的参数大都为name和step,name取值为bsp、device、core、service、feature、run,step取值为0。从⑺和⑻处可以看出,分别调用SYS_CALL、MODULE_CALL两个宏,第二个参数设置为0。⑸处定义的MODULE_BEGIN函数,用于返回链接脚本中定义的代码段的开始地址,当传入参数为bsp时,返回&__zinitcall_bsp_start,MODULE_BEGIN函数被展开为如下片段:

{        extern InitCall __zinitcall_sys_start;      \
        InitCall *initCall = &__zinitcall_bsp_start; \
        (initCall);                                      \
}

⑹处定义的MODULE_END函数,用于返回链接脚本中定义的代码段的结束地址,当传入参数为bsp时,返回&__zinitcall_bsp_end,MODULE_END函数被展开为如下片段:

{        extern InitCall __zinitcall_bsp_end;      \
        InitCall *initCall = &__zinitcall_bsp_end; \
        (initCall);                                    \
}    

⑶和⑷处定义的SYS_BEGIN、SYS_END代码类似,分于返回链接脚本中定义的标记系统服务或特性的代码段的开始、结束地址,即&__zinitcall_sys_service_start、&__zinitcall_sys_service_end、&__zinitcall_sys_feature_start、&__zinitcall_sys_feature_end。⑴处定义的SYS_CALL函数,分别获取链接脚本中zInit代码段的开始initcall和结束地址initend,这些地址存放的是初始化函数的地址,语句 (*initcall)()会循环调用执行这些初始化函数。⑵处MODULE_CALL宏类似。

⑴  #define SYS_CALL(name, step)                                      \
        do {                                                          \
            InitCall *initcall = (InitCall *)(SYS_BEGIN(name, step)); \
            InitCall *initend = (InitCall *)(SYS_END(name, step));    \
            for (; initcall < initend; initcall++) {                  \
                (*initcall)();                                        \
            }                                                         \
        } while (0)

⑵  #define MODULE_CALL(name, step)                                      \
        do {                                                             \
            InitCall *initcall = (InitCall *)(MODULE_BEGIN(name, step)); \
            InitCall *initend = (InitCall *)(MODULE_END(name, step));    \
            for (; initcall < initend; initcall++) {                     \
                (*initcall)();                                           \
            }                                                            \
        } while (0)

    ......
⑶  #define SYS_BEGIN(name, step)                                 \
        ({        extern InitCall __zinitcall_sys_##name##_start;       \
            InitCall *initCall = &__zinitcall_sys_##name##_start; \
            (initCall);                                           \
        })

⑷  #define SYS_END(name, step)                                 \
        ({        extern InitCall __zinitcall_sys_##name##_end;       \
            InitCall *initCall = &__zinitcall_sys_##name##_end; \
            (initCall);                                         \
        })

⑸  #define MODULE_BEGIN(name, step)                          \
        ({        extern InitCall __zinitcall_##name##_start;       \
            InitCall *initCall = &__zinitcall_##name##_start; \
            (initCall);                                       \
        })
⑹  #define MODULE_END(name, step)                          \
        ({        extern InitCall __zinitcall_##name##_end;       \
            InitCall *initCall = &__zinitcall_##name##_end; \
            (initCall);                                     \
        })

⑺  #define SYS_INIT(name)     \
        do {                   \
            SYS_CALL(name, 0); \
        } while (0)

⑻  #define MODULE_INIT(name)     \
        do {                      \
            MODULE_CALL(name, 0); \
        } while (0)

3、 bootstrap_lite服务启动引导部件实现原理之bootstrap_service

在文件base\startup\bootstrap_lite\services\source\bootstrap_service.h中定义了2个宏函数INIT_APP_CALL和INIT_TEST_CALL,分别用来调用代码段&__zinitcall_app_XXX_start、&__zinitcall_app_XXX_end和&__zinitcall_test_start、&__zinitcall_test_end之间的初始化启动函数。bootstrap_service.h文件中的宏和base\startup\bootstrap_lite\services\source\core_main.h文件中的宏类似,不再一一分析。

3.1 结构体struct Bootstrap

在文件base\startup\bootstrap_lite\services\source\bootstrap_service.c中定义了结构体struct Bootstrap,如下代码⑵处。其中结构体中的INHERIT_SERVICE定义在文件foundation/distributedschedule/samgr_lite/interfaces/kits/samgr/service.h,见代码片段⑴处。


⑴   #define INHERIT_SERVICE                                          \
        const char *(*GetName)(Service * service);                   \
        BOOL (*Initialize)(Service * service, Identity identity);    \
        BOOL (*MessageHandle)(Service * service, Request * request); \
        TaskConfig (*GetTaskConfig)(Service * service)

    ......
⑵  typedef struct Bootstrap {
        INHERIT_SERVICE;
        Identity identity;
        uint8 flag;
    } Bootstrap;

结构体Identity定义在文件foundation\distributedschedule\samgr_lite\interfaces\kits\samgr\message.h中,用于标识一个服务或特性。

/**
 * @brief Identifies a service and feature.
 *
 * You can use this structure to identity a {@link IUnknown} feature to which messages will be
 * sent through the asynchronous function of {@link IUnknown}. \n
 *
 */
struct Identity {
    /** Service ID */
    int16 serviceId;
    /** Feature ID */
    int16 featureId;
    /** Message queue ID */
    MQueueId queueId;
};

3.2 Init(void)函数

讲解移植适配示例时,我们已经知道,bootstrap_lite部件会编译//base/startup/bootstrap_lite/services/source/bootstrap_service.c,该文件通过函数宏SYS_SERVICE_INIT将Init()函数符号灌段到__zinitcall_sys_service_start和__zinitcall_sys_service_end代码段中,代码片段如下。下文再详细分析GetName、Initialize、MessageHandle和GetTaskConfig函数。

  static const char *GetName(Service *service);
  static BOOL Initialize(Service *service, Identity identity);
  static TaskConfig GetTaskConfig(Service *service);
  static BOOL MessageHandle(Service *service, Request *request);

  static void Init(void)
  {
      static Bootstrap bootstrap;
      bootstrap.GetName = GetName;
      bootstrap.Initialize = Initialize;
      bootstrap.MessageHandle = MessageHandle;
      bootstrap.GetTaskConfig = GetTaskConfig;
      bootstrap.flag = FALSE;
      SAMGR_GetInstance()->RegisterService((Service *)&bootstrap);
  }
  SYS_SERVICE_INIT(Init);

3.3 GetName和Initialize函数

GetName函数代码如下,其中BOOTSTRAP_SERVICE定义在文件foundation\distributedschedule\samgr_lite\interfaces\kits\samgr\samgr_lite.h中,取值为"Bootstrap",表示启动引导服务。

static const char *GetName(Service *service)
{
    (void)service;
    return BOOTSTRAP_SERVICE;
}

Initialize函数定义如下,用于设置启动引导服务的标识信息。

static BOOL Initialize(Service *service, Identity identity)
{
    Bootstrap *bootstrap = (Bootstrap *)service;
    bootstrap->identity = identity;
    return TRUE;
}

3.4 MessageHandle函数和GetTaskConfig函数

MessageHandle函数和GetTaskConfig函数代码如下,MessageHandle函数用于处理各种请求,请求消息编号定义request->msgId定义在文件foundation\distributedschedule\samgr_lite\interfaces\kits\samgr\samgr_lite.h中的枚举enum BootMessage,如下⑴处所示。在MessageHandle函数中,当请求的消息编号为BOOT_SYS_COMPLETED系统服务初始化完成时,检查应用服务是否加载。当应用没有加载时,执行INIT_APP_CALL宏函数调用zInit代码段上的应用服务和应用特性初始化函数。然后执行⑶,调用函数SAMGR_SendResponseByIdentity进行响应。GetTaskConfig函数用于获取任务配置。

⑴  typedef enum BootMessage {
        /** Message indicating that the core system service is initialized */
        /** 标识核心系统服务初始化完成 */
        BOOT_SYS_COMPLETED,
        /** Message indicating that the system and application-layer services are initialized */
        /** 标识应用层服务初始化完成 */
        BOOT_APP_COMPLETED,
        /** Message indicating service registration during running */
        /** 标识运行时的服务注册 */
        BOOT_REG_SERVICE,
        /** Maximum number of message IDs */
        /** 标识消息最大值,butt是烟蒂;屁股;枪托的意思,表示尾部吧 */
        BOOTSTRAP_BUTT
    } BootMessage;
    ......
  static BOOL MessageHandle(Service *service, Request *request)
  {
      Bootstrap *bootstrap = (Bootstrap *)service;
      switch (request->msgId) {
          case BOOT_SYS_COMPLETED:if ((bootstrap->flag & LOAD_FLAG) != LOAD_FLAG) {
                  INIT_APP_CALL(service);
                  INIT_APP_CALL(feature);
                  bootstrap->flag |= LOAD_FLAG;
              }
            (void)SAMGR_SendResponseByIdentity(&bootstrap->identity, request, NULL);
              break;

          case BOOT_APP_COMPLETED:
              (void)SAMGR_SendResponseByIdentity(&bootstrap->identity, request, NULL);
              break;

          case BOOT_REG_SERVICE:
              (void)SAMGR_SendResponseByIdentity(&bootstrap->identity, request, NULL);
              break;

          default:
              break;
      }
      return TRUE;
  }

  static TaskConfig GetTaskConfig(Service *service)
  {
      (void)service;
      // The bootstrap service uses a stack of 2 KB (0x800) in size and a queue of 20 elements.
      // You can adjust it according to the actual situation.
      TaskConfig config = {LEVEL_HIGH, PRI_NORMAL, 0x800, 20, SHARED_TASK};
      return config;
  }

参考站点

小结

本文介绍了startup子系统之bootstrap_lite服务启动引导部件的移植适配案例及原理。因为时间关系,仓促写作,或能力限制,若有失误之处,请各位读者多多指正。感谢阅读,有什么问题,请留言。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。