OpenHarmony轻量系统服务管理|消息广播服务及其子功能详解

一、前言

本文相关代码实现位于distributedschedule_samgr_lite\communication\broadcast\source\目录下的broadcast_service.cpub_sub_feature.c。 本文将对以下数据结构及函数进行详解。

    struct BroadcastService:
    struct ConsumerNode:
    struct Relation:
    struct PubSubFeature:
    在broadcast_service.c中
    Init:注册广播服务
    GetName:获取广播服务的名称
    Initialize:广播服务的初始化函数
    MessageHandle:广播服务的消息处理函数
    GetTaskConfig:获取广播服务的任务配置
    在pub_sub_feature.c中
    Init:初始化全局广播变量
    GetName:获取功能名称
    OnInitialize:初始化ID
    OnStop:停止功能
    OnMessage:广播子功能的消息处理函数
    GetRelation:获取子功能与主题的关系
    IsTopicEqual:判断两个主题是否相等

二、数据结构分析

广播服务的数据结构
//广播服务消息类型
enum BroadcastMsgType {
    BROADCAST_MSG,      //消息类型
};
typedef struct BroadcastService BroadcastService;
//广播服务
struct BroadcastService {
    INHERIT_SERVICE;    //继承服务基类
};
//全局广播服务
static BroadcastService g_broadcastService = {
    GetName,
    Initialize,
    MessageHandle,
    GetTaskConfig,
};
广播服务子功能
//消费者结点
typedef struct ConsumerNode {
    UTILS_DL_LIST node;     //双向链表,包含prev和next指针
    Consumer *consumer;     //消费者
} ConsumerNode;
//关系,topic和消费者,一个topic对应多个消费者,消费者存储在双向链表中
typedef struct Relation {
    UTILS_DL_LIST node;     //双向链表,包含prev和next指针
    ConsumerNode callbacks; //消费者结点集合,为一个双向循环链表
    Topic topic;            //消息标识
} Relation;
typedef struct PubSubFeature PubSubFeature;
//一个id对应一个关系双向链表,关系中又包含了一个topic和一个消费者双向链表
//一个PubSubFeature结点可以由identity标识,包含一系列关系组合
//一个relation结点可以由topic标识,包含一组消费者集合
struct PubSubFeature {
    INHERIT_FEATURE;    //继承功能基类
    //函数指针,用于获取指定功能下的topic和消费者的关系
    Relation *(*GetRelation)(PubSubFeature *feature, const Topic *topic);
    MutexId mutex;          //锁
    Relation relations;     //关系,双向循环链表
    Identity identity;      //身份标识,标识服务ID、功能ID和消息队列ID
};

三、函数实现详解

广播服务的函数

注册广播服务
//注册广播服务
static void Init(void)
{
    SAMGR_GetInstance()->RegisterService((Service *)&g_broadcastService);
}
SYS_SERVICE_INIT(Init);
获取服务名称
//获取广播服务的名称
static const char *GetName(Service *service)
{
    (void)service;
    return BROADCAST_SERVICE;
}
初始化广播服务
//广播服务的初始化函数,当前代码版本暂未实现
static BOOL Initialize(Service *service, Identity identity)
{
    (void)identity;
    if (service == NULL) {
        return FALSE;
    }
    return TRUE;
}
广播服务的处理函数
//广播服务的消息处理函数,当前代码版本暂未实现
static BOOL MessageHandle(Service *service, Request *request)
{
    (void)service;
    switch (request->msgId) {
        case BROADCAST_MSG:
            break;
        default:
            break;
    }
    return TRUE;
}
获取广播服务的任务配置
//获取广播服务的任务配置
static TaskConfig GetTaskConfig(Service *service)
{
    (void)service;
    //默认配置
    TaskConfig config = {LEVEL_HIGH, PRI_ABOVE_NORMAL, 0x800, 40, SPECIFIED_TASK};
    return config;
}

广播功能的函数

初始化广播功能
//初始化g_broadcastFeature,并注册feature和feature的接口
static void Init(void)
{
    //获取全局广播服务子功能
    PubSubFeature *feature = &g_broadcastFeature;
    //初始化关系链表的头结点
    feature->relations.topic = -1;
    feature->relations.callbacks.consumer = NULL;
    //初始化关系的双向链表,让prev和next都指向自身
    UtilsListInit(&feature->relations.callbacks.node);
    UtilsListInit(&feature->relations.node);
    //申请锁
    feature->mutex = MUTEX_InitValue();
    //将feature注册到服务BROADCAST_SERVICE中
    SAMGR_GetInstance()->RegisterFeature(BROADCAST_SERVICE, (Feature *)feature);
    //通过feature创建一个PubSubImplement实例
    PubSubImplement *apiEntry = BCE_CreateInstance((Feature *)feature);
    //为feature注册接口
    SAMGR_GetInstance()->RegisterFeatureApi(BROADCAST_SERVICE, PUB_SUB_FEATURE, GET_IUNKNOWN(*apiEntry));
}
SYS_FEATURE_INIT(Init);
获取功能名称
//初始化g_broadcastFeature,并注册feature和feature的接口
static void Init(void)
{
    //获取全局广播服务子功能
    PubSubFeature *feature = &g_broadcastFeature;
    //初始化关系链表的头结点
    feature->relations.topic = -1;
    feature->relations.callbacks.consumer = NULL;
    //初始化关系的双向链表,让prev和next都指向自身
    UtilsListInit(&feature->relations.callbacks.node);
    UtilsListInit(&feature->relations.node);
    //申请锁
    feature->mutex = MUTEX_InitValue();
    //将feature注册到服务BROADCAST_SERVICE中
    SAMGR_GetInstance()->RegisterFeature(BROADCAST_SERVICE, (Feature *)feature);
    //通过feature创建一个PubSubImplement实例
    PubSubImplement *apiEntry = BCE_CreateInstance((Feature *)feature);
    //为feature注册接口
    SAMGR_GetInstance()->RegisterFeatureApi(BROADCAST_SERVICE, PUB_SUB_FEATURE, GET_IUNKNOWN(*apiEntry));
}
SYS_FEATURE_INIT(Init);
初始化身份标识
//为feature配置身份标识
static void OnInitialize(Feature *feature, Service *parent, Identity identity)
{
    (void)parent;
    ((PubSubFeature *)feature)->identity = identity;
}
停止广播功能
//停止指定的功能
static void OnStop(Feature *feature, Identity identity)
{
    (void)feature;
    (void)identity;
}
广播功能的消息处理
/*
    函数功能:广播功能的消息处理函数
    函数参数:@feature:功能对象
             @request:请求消息
    函数返回:处理成功 返回TRUE,处理失败 返回FALSE
    函数描述:根据请求消息的消息类型执行不同的处理逻辑。这里只实现了MSG_PUBLISH类型的消息的处理方法。
*/
static BOOL OnMessage(Feature *feature, Request *request)
{
    //获取广播功能对象
    PubSubFeature *broadcast = (PubSubFeature *)feature;
    switch (request->msgId) {//获取消息ID
        case MSG_PUBLISH: {//消息类型为发布
            //获取消息值,存储的是topic值,使用msgValue一般传输的是小消息,更快和便携。而使用data传输大消息
            Topic topic = request->msgValue;
            //获取广播功能与topic的关系
            Relation *relation = broadcast->GetRelation(broadcast, &topic);
            if (relation == NULL) {
                //无关系,则返回false
                return FALSE;
            }//找到关系
            //加锁
            MUTEX_Lock(broadcast->mutex);
            ConsumerNode *item = NULL;
            /*
                UTILS_DL_LIST_FOR_EACH_ENTRY(item, list, type, member)用于迭代给定类型的双链表
                UTILS_DL_LIST_ENTRY(item, type, member)用于获取指向包含双链表的结构的指针
            */
            //遍历指定关系下的消费者集合的双向链表,遍历topic下的每一个消费者的信息
            UTILS_DL_LIST_FOR_EACH_ENTRY(item, &relation->callbacks.node, ConsumerNode, node) {
                //消费者的身份ID为NULL
                if (item->consumer->identity == NULL) {
                    //消费者处理已发布的topic中的事件或数据
                    item->consumer->Notify(item->consumer, &topic, request);
                }
            }
            MUTEX_Unlock(broadcast->mutex);
        }
            break;
        default:
            break;
    }
    return TRUE;
}
获取广播功能中特定topic的关系
//获取给定的topic在feature中的关系
static Relation *GetRelation(PubSubFeature *feature, const Topic *topic)
{
    //参数检查
    if (feature == NULL || topic == NULL) {
        return NULL;
    }
    //获取指定功能的关系集合头结点,这是一个双向链表
    UTILS_DL_LIST *list = &feature->relations.node;
    Relation *item = NULL;
    MUTEX_Lock(feature->mutex);
    //遍历关系集合的链表,获取每一个关系的信息
    UTILS_DL_LIST_FOR_EACH_ENTRY(item, list, Relation, node) {
        if (IsTopicEqual(&item->topic, topic)) {//判断两个topic的值是否相等
            //topic匹配成功,返回对应的relation
            MUTEX_Unlock(feature->mutex);
            return item;
        }
    }
    MUTEX_Unlock(feature->mutex);
    return NULL;
}
判断topic是否相同
//判断两个topic的值是否相等
static BOOL IsTopicEqual(const Topic *current, const Topic *other)
{
    return *current == *other;
}

总是有很多小伙伴反馈说:鸿蒙开发不知道学习哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点? 为了解决大家这些学习烦恼。在这准备了一份很实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档给大家用来跟着学习。

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……


在这里插入图片描述

开发基础知识

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN/733GH/overview

OpenHarmony 开发环境搭建:https://gitcode.com/HarmonyOS_MN/733GH/overview


在这里插入图片描述

《OpenHarmony源码解析》

搭建开发环境
系统架构分析

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN

在这里插入图片描述

  • 21
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值