本文继续分析samgr_lite的函数实现。文件位于distributedschedule_samgr_lite\samgr\source\samgr_lite.c
函数实现分析
添加任务池
/*
函数功能:为服务绑定任务池
函数参数:@service:ServiceImpl对象
@cfg:任务池配置
@name:service的name
函数描述:任务池的绑定分为三种,根据服务的任务类型选择不同的方案。
首先进行任务配置的优先级检查,防止出现非法值,导致共享任务池数组越界
然后根据服务任务类型绑定不同的任务池,分为一下三种方案:
1.SHARED_TASK:按照当前任务配置cfg的优先级来确定应该绑定到sharedPool中的哪一个任务池
2.SPECIFIED_TASK:在services的集合中查找是否存在与指定的任务配置cfg相同的任务池,若存在则绑定,若不存在则进入SINGLE_TASK
3.SINGLE_TASK:根据任务配置cfg创建新的任务池
*/
static void AddTaskPool(ServiceImpl *service, TaskConfig *cfg, const char *name)
{
//如果当前service已分配taskpool,则返回
if (service->taskPool != NULL) {
return;
}
//未分配taskpoll,进行分配
if (cfg->priority < PRI_LOW || cfg->priority >= PRI_BUTT) {
//参数不合法,记录日志
HILOG_ERROR(HILOG_MODULE_SAMGR, "The %s service pri(%d) is out of range!", name, cfg->priority);
//更新优先级为最低级
cfg->priority = PRI_LOW;
}
//判断任务类型
switch (cfg->taskFlags) {
case SHARED_TASK: {
//根据服务的优先级共享任务
int pos = (int)cfg->priority / PROPERTY_STEP;//优先级与步长的结果正好对应到1,2,3,4
SamgrLiteImpl *samgr = GetImplement();
//若为NULL,则创建一个默认配置的任务池
if (samgr->sharedPool[pos] == NULL) {
TaskConfig shareCfg = DEFAULT_TASK_CFG(pos);
/*
函数功能:创建一个任务池和相应的队列
函数参数:@1:service的任务配置,包括任务优先级、堆栈大小、队列大小、任务类型和共享任务ID
@2:队列名称
@3:维护的线程ID数组大小
*/
samgr->sharedPool[pos] = SAMGR_CreateFixedTaskPool(&shareCfg, name, DEFAULT_SIZE);
}
//给service配置任务池
service->taskPool = samgr->sharedPool[pos];
//引用对应的任务池,增加任务池的引用计数
if (SAMGR_ReferenceTaskPool(service->taskPool) == NULL) {
//任务池为NULL或者任务池的引用已达到上限。
HILOG_ERROR(HILOG_MODULE_SAMGR, "shared task:%p pri:%d ref is full", service->taskPool, cfg->priority);
samgr->sharedPool[pos] = NULL;
}
}
break;
case SPECIFIED_TASK:
//由多个服务共享的指定任务
//查找是否存在与cfg配置相同的任务池,即多个服务共享同一个任务池
service->taskPool = GetSpecifiedTaskPool(cfg);
if (service->taskPool != NULL) {
//若找到,则结束switch,若未找到则进入SINGLE_TASK
break;
}
case SINGLE_TASK:
//服务独占的任务
//根据当前的任务配置,创建一个新的任务池
service->taskPool = SAMGR_CreateFixedTaskPool(cfg, name, SINGLE_SIZE);
break;
default:
break;
}
if (service->taskPool == NULL) {
//记录错误日志
HILOG_ERROR(HILOG_MODULE_SAMGR, "Service<name:%s, flag:%d> create taskPool failed!", name, cfg->taskFlags);
}
}
发送启动请求
/*
函数功能:发送与启动相关的消息
函数参数:@msgId:消息类型
@msgValue:消息值
函数描述:BOOTSTRAP_SERVICE服务向消息队列发送消息,消息包含消息类型和消息值
*/
static int32 SendBootRequest(int msgId, uint32 msgValue)
{
/*
①获取name为BOOTSTRAP_SERVICE的serviceImpl对象
②根据serviceImpl和feature返回相应的identity
*/
Identity id = DEFAULT_GetFeatureId(GetService(BOOTSTRAP_SERVICE), NULL);
//构建消息request
Request request = {msgId, 0, NULL, msgValue};
/*
函数功能:将请求放入消息队列中
函数参数:@1:标识服务或特性的ID
@2:消息
@3:消息处理函数
函数返回:成功 返回EC_SUCCESS,失败 返回EC_INVALID or EC_BUSBUSY
*/
return SAMGR_SendRequest(&id, &request, (Handler)SAMGR_Bootstrap);
}
处理初始化的请求消息
//处理消息的函数,负责服务的初始化
static void HandleInitRequest(const Request *request, const Response *response)
{
//从消息中获取serviceImpl对象
ServiceImpl *serviceImpl = (ServiceImpl *)request->data;
if (serviceImpl == NULL) {
HILOG_ERROR(HILOG_MODULE_SAMGR, "Init service Request:<%d,%d>, Response:<%p,%d>!",
request->msgId, request->msgValue, response->data, response->len);
return;
}
//记录 处理的最新的一条消息的时间戳
uint32 lastTime = serviceImpl->ops.timestamp;
//初始化ServiceImpl,并初始化ServiceImpl的features中所有的FeatureImpl
DEFAULT_Initialize(serviceImpl);
//获取最新的时间戳
serviceImpl->ops.timestamp = SAMGR_GetProcessTime();
//更新为闲置状态
serviceImpl->inited = SVC_IDLE;
HILOG_INFO(HILOG_MODULE_SAMGR, "Init service %s <time: %ums> success!",
serviceImpl->service->GetName(serviceImpl->service), serviceImpl->ops.timestamp - lastTime);
//判断是否对所有服务都进行了初始化
int32 err = InitCompleted();
if (err != EC_SUCCESS) {
HILOG_INFO(HILOG_MODULE_SAMGR, "Goto next boot step return code:%d", err);
}
}
初始化指定服务
//初始化单个service
static void InitializeSingleService(ServiceImpl *service)
{
//若service绑定的任务池为NULL,则直接进行初始化
if (service->taskPool == NULL) {
DEFAULT_Initialize(service);
return;
}
//已绑定任务池,则向消息队列发送初始化服务的请求
//构建ID信息
Identity identity = {service->serviceId, INVALID_INDEX, service->taskPool->queueId};
//构建消息,将service作为数据段
Request request = {0, 0, service, 0};
uint32 *ref = NULL;
//向特性线程发送调用者的请求和响应。直接调用HandleInitRequest来处理请求和响应,而不使用消息处理函数。
(void)SAMGR_SendSharedDirectRequest(&identity, &request, NULL, &ref, HandleInitRequest);
}
查找指定任务配置的任务池
/*
函数功能:查找指定任务配置的任务池
函数返回:查找成功返回该任务池,查找失败返回NULL
函数描述:遍历samgr中维护的服务,查找与指定任务配置相同的服务。
若找到相同任务配置的服务,则判断绑定的任务池是否为NULL。!=NULL时,增加任务池的引用数并返回它,==NULL时返回NULL。
若未找到相同任务配置的服务,则返回NULL。
*/
static TaskPool *GetSpecifiedTaskPool(TaskConfig *config)
{
//获取samgr对象
SamgrLiteImpl *samgr = GetImplement();
//获取service集合
Vector *services = &(samgr->services);
MUTEX_Lock(samgr->mutex);
//获取services中ServiceImpl的个数
int16 serviceNum = VECTOR_Size(services);
int i;
//遍历所有服务的任务配置
for (i = 0; i < serviceNum; ++i) {
//获取服务实例
ServiceImpl *impl = VECTOR_At(services, i);
if (impl == NULL) {
continue;
}
//获取任务配置
TaskConfig cfg = impl->service->GetTaskConfig(impl->service);
//寻找ServiceImpl中的任务配置与当前指定的config相同的service
if (memcmp(&cfg, config, sizeof(TaskConfig)) != 0) {
continue;
}
//若匹配到,但绑定的任务池为NULL,则结束循环
if (impl->taskPool == NULL) {
break;
}
//绑定的任务池不为NULL,增加该任务池的引用数并返回它
TaskPool *taskPool = SAMGR_ReferenceTaskPool(impl->taskPool);
if (taskPool != NULL) {
MUTEX_Unlock(samgr->mutex);
return taskPool;
}
}
MUTEX_Unlock(samgr->mutex);
return NULL;
}
samgr_lite部分的函数终于分析完毕。
总是有很多小伙伴反馈说:OpenHarmony开发不知道学习哪些技术?不知道需要重点掌握哪些OpenHarmony开发知识点? 为了解决大家这些学习烦恼。在这准备了一份很实用的鸿蒙全栈开发学习路线与学习文档给大家用来跟着学习。
针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植……等)技术知识点。
OpenHarmony 开发环境搭建:https://gitcode.com/HarmonyOS_MN/733GH/overview
《OpenHarmony源码解析》
搭建开发环境
系统架构分析
- 构建子系统
- 启动流程
- 子系统
- 分布式任务调度子系统
- 分布式通信子系统
- 驱动子系统
- ……