OpenHarmony轻量系统服务管理samgr-task_manager赏析及实现(1)

一、前言

在task_manager部分,主要负责对任务的管理,从消息队列获取消息并处理。在distributedschedule_samgr_lite\samgr\source\task_manager.h中对声明对任务池操作的方法。在distributedschedule_samgr_lite\samgr\source\task_manager.c中对相关方法进行了实现。

二、头文件分析

#ifndef MAX_TASK_SIZE
#define MAX_TASK_SIZE 0xFFFFFF  //任务的最大数
#endif
//引用的最大数
#define MAX_REF_NUM 15          
//消息处理的最大时间间隔
#define MSG_PROC_THRESHOLD (10 * 1000)
#define GET_REMAIN_TIME(time) ((0xFFFFFFFF - (time)) + 1)
//计算时间间隔
#define GET_INTERVAL(last, now) (((last) > (now)) ? (GET_REMAIN_TIME(last) + (now)) : ((now) - (last)))
typedef struct TaskPool TaskPool;
struct TaskPool {
    MQueueId queueId;   //消息队列ID
    uint16 stackSize;   //栈大小,用于配置线程的栈
    uint8 priority;     //任务的优先级,用于配置线程的优先级
    uint8 size;         //任务池的大小,维护的线程数
    uint8 top;          //标识tasks中的线程ID的个数 
    int8 ref;           //引用数
    ThreadId tasks[0];  //记录任务池下属的线程ID
};
//创建任务池
TaskPool *SAMGR_CreateFixedTaskPool(const TaskConfig *config, const char *name, uint8 size);
//启动任务池
int32 SAMGR_StartTaskPool(TaskPool *pool, const char *name);
//释放任务池
int32 SAMGR_ReleaseTaskPool(TaskPool *pool);
//引用任务池
TaskPool *SAMGR_ReferenceTaskPool(TaskPool *pool);
//获取当前的消息队列ID
MQueueId SAMGR_GetCurrentQueueID(void);

函数实现分析

任务池的创建

#ifndef MAX_TASK_SIZE
#define MAX_TASK_SIZE 0xFFFFFF  //任务的最大数
#endif
//引用的最大数
#define MAX_REF_NUM 15          
//消息处理的最大时间间隔
#define MSG_PROC_THRESHOLD (10 * 1000)
#define GET_REMAIN_TIME(time) ((0xFFFFFFFF - (time)) + 1)
//计算时间间隔
#define GET_INTERVAL(last, now) (((last) > (now)) ? (GET_REMAIN_TIME(last) + (now)) : ((now) - (last)))
typedef struct TaskPool TaskPool;
struct TaskPool {
    MQueueId queueId;   //消息队列ID
    uint16 stackSize;   //栈大小,用于配置线程的栈
    uint8 priority;     //任务的优先级,用于配置线程的优先级
    uint8 size;         //任务池的大小,维护的线程数
    uint8 top;          //标识tasks中的线程ID的个数 
    int8 ref;           //引用数
    ThreadId tasks[0];  //记录任务池下属的线程ID
};
//创建任务池
TaskPool *SAMGR_CreateFixedTaskPool(const TaskConfig *config, const char *name, uint8 size);
//启动任务池
int32 SAMGR_StartTaskPool(TaskPool *pool, const char *name);
//释放任务池
int32 SAMGR_ReleaseTaskPool(TaskPool *pool);
//引用任务池
TaskPool *SAMGR_ReferenceTaskPool(TaskPool *pool);
//获取当前的消息队列ID
MQueueId SAMGR_GetCurrentQueueID(void);

任务池的启动

/*
    函数功能:启动任务池
    函数参数:@pool:指向任务池的指针
             @name:创建的线程名
    函数返回:成功 返回EC_SUCCESS,失败 返回EC_INVALID
    函数描述:向任务池中添加新创建的线程,创建的线程数等于pool->size值
*/
int32 SAMGR_StartTaskPool(TaskPool *pool, const char *name)
{
    //参数检查
    if (pool == NULL) {
        return EC_INVALID;
    }
    //任务池中维护的线程数大于0时,返回EC_SUCCESS
    if (pool->top > 0) {
        return EC_SUCCESS;
    }
    //后续语句为pool->top小于或等于0才会执行
    //配置线程属性
    ThreadAttr attr = {name, pool->stackSize, pool->priority, 0, 0};
    //创建pool->size个线程
    while (pool->top < pool->size) {
        /*
            创建线程,运行的函数为TaskEntry
            @1:创建的线程开始运行的函数地址
            @2:运行函数需要的参数
            @3:线程属性
        */
        register ThreadId threadId = (ThreadId)THREAD_Create(TaskEntry, pool->queueId, &attr);
        if (threadId == NULL) {
            //记录错误日志
            HILOG_ERROR(HILOG_MODULE_SAMGR, "Start Task<%s, %d, %d> failed!", name, pool->stackSize, pool->priority);
            break;
        }
        //记录线程ID
        pool->tasks[pool->top] = threadId;
        ++(pool->top);
    }
    return EC_SUCCESS;
}

释放任务池的内存

/*
    函数功能:释放任务池的内存
    函数返回:成功 返回EC_SUCCESS,失败 返回EC_INVALID
    函数描述:更新任务池的引用数,若==0则构建消息类型为MSG_EXIT的exchange对象,发送到消息队列中,指示本任务池中的线程退出。并释放任务池。
*/
int32 SAMGR_ReleaseTaskPool(TaskPool *pool)
{
    if (pool == NULL) {
        return EC_INVALID;
    }
    //对任务池的引用计数减一
    pool->ref--;
    if (pool->ref == 0) {
        //如果任务池未被其他对象引用,则回收资源
        //初始化一个MSG_EXIT类型的exchange对象
        Exchange exchange = {0};
        //消息类型为MSG_EXIT,当任务池中的线程处理到消息队列中的这条消息时,会停止执行并退出
        exchange.type = MSG_EXIT;
        //将类型为MSG_EXIT的exchange对象发送到任务池绑定的消息队列中
        QUEUE_Put(pool->queueId, &exchange, 0, DONT_WAIT);
        //释放资源
        SAMGR_Free(pool);
    }
    return EC_SUCCESS;
}

增加任务池的引用数

//引用对应的任务池,增加任务池的引用计数
TaskPool *SAMGR_ReferenceTaskPool(TaskPool *pool)
{
    if (pool == NULL) {
        return NULL;
    }
    if (pool->ref >= MAX_REF_NUM) {
        //引用数超出最大值
        return NULL;
    }
    //引用数自增
    pool->ref++;
    return pool;
}

task_manager剩下的部分实现将在下一篇进行分析。

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

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植……等)技术知识点。

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


在这里插入图片描述

《OpenHarmony源码解析》

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

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

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

在这里插入图片描述

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值