往期知识点记录:
- 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
- OpenHarmony轻量系统服务管理-samgr主要接口思维导图(1)
- OpenHarmony轻量系统服务管理-samgr主要接口思维导图(2)
- OpenHarmony轻量系统服务管理-samgr:common赏析及实现
- OpenHarmony轻量系统服务管理-samgr:iunknown赏析
- OpenHarmony轻量系统服务管理-samgr:iunknown实现分析
- OpenHarmony轻量系统服务管理samgr-message赏析
- OpenHarmony轻量系统服务管理samgr-message实现分析(1)
- OpenHarmony轻量系统服务管理samgr-message实现分析(2)
- OpenHarmony轻量系统服务管理samgr-service赏析
- OpenHarmony轻量系统服务管理samgr-samgr_lite赏析
- OpenHarmony轻量系统服务管理samgr-feature赏析及实现
- OpenHarmony轻量系统服务管理samgr-service实现分析(1)
- OpenHarmony轻量系统服务管理samgr-service实现分析(2)
- OpenHarmony轻量系统服务管理samgr-task_manager赏析及实现(1)
- OpenHarmony轻量系统服务管理samgr-task_manager赏析及实现(2)
- 持续更新中……
本文继续对任务管理器的实现进行分析。
任务执行入口函数,当前函数是线程创建时的运行函数
/*
函数功能:循环读取消息队列中的消息,并处理
函数描述:不断的从绑定的消息队列中读取消息,根据消息的类型调用不同的处理函数。
在处理消息前,若serviceImpl的状态为SVC_IDLE,则更新为SVC_BUSY。
对于MSG_EXIT类型的消息,回收资源并退出线程。
对于MSG_ACK和MSG_DIRECT类型的消息,直接调用exchange的响应处理函数handler处理。
对于MSG_EXIT、MSG_ACK和MSG_DIRECT类型以外的消息,调用服务或子功能的消息处理函数处理。
消息处理完后,若serviceImpl的状态为SVC_BUSY,则更新为SVC_IDLE。
*/
static void *TaskEntry(void *argv)
{
ServiceImpl *serviceImpl = NULL;
//将消息队列ID存到当前线程的私有变量中。将当前线程与指定任务池中的消息队列绑定。
THREAD_SetThreadLocal(argv);
//循环处理消息队列中的消息
while (TRUE) {
Exchange exchange;
//从指定的消息队列接收消息,会因为QUEUE_Pop()函数而阻塞
uint32 msgRcvRet = SAMGR_MsgRecv((MQueueId)argv, (uint8 *)&exchange, sizeof(Exchange));
if (msgRcvRet != EC_SUCCESS) {
//读取消息失败
continue;
}
//消息接收成功
//消息类型为退出,退出当前线程
if (exchange.type == MSG_EXIT) {
//判断exchange对象的引用计数是否为0,若为0则释放request.data、response.data和sharedref所指向的动态内存,否则不会释放,只是引用计数减一
SAMGR_FreeMsg(&exchange);
break;
}
//通过接收到的exchange对象更新serviceImpl
serviceImpl = CorrectServiceImpl(&exchange, serviceImpl);
//更新ServiceImpl的消息处理数和时间戳,并更改状态为SVC_BUSY
BeginWork(serviceImpl);
//当消息类型为MSG_ACK时,执行响应处理函数
ProcResponse(&exchange);
//处理MSG_DIRECT类型的消息
ProcDirectRequest(&exchange);
//处理除MSG_ACK和MSG_DIRECT以外的消息
ProcRequest(&exchange, serviceImpl);
//消息处理结束,更新状态为SVC_IDLE
EndWork(serviceImpl, &exchange);
//判断exchange对象的引用计数是否为0,若为0则释放request.data、response.data和sharedref所指向的动态内存,否则不会释放,只是引用计数减一
SAMGR_FreeMsg(&exchange);
}
//退出时销毁消息队列
QUEUE_Destroy((MQueueId)argv);
return NULL;
}
处理MSG_NON/MSG_CON/MSG_SYNC类型的消息
//通过服务或子功能的消息处理函数处理MSG_NON/MSG_CON/MSG_SYNC类型的消息,当消息类型为MSG_CON时,发送相应的回复
static void ProcRequest(Exchange *exchange, ServiceImpl *serviceImpl)
{
//参数检查
if (serviceImpl == NULL || exchange->type == MSG_ACK || exchange->type == MSG_DIRECT) {
return;
}
//处理消息,若featureID不为NULL,则调用指定feature的消息处理函数,若为NULL,则调用service的消息处理函数
DEFAULT_MessageHandle(serviceImpl, &(exchange->id), &(exchange->request));
if (exchange->type == MSG_CON) {
//发送响应
SAMGR_SendResponse(&exchange->request, &exchange->response);
}
}
处理MSG_ACK类型的消息
//当消息类型为MSG_ACK时,执行响应处理函数
static void ProcResponse(Exchange *exchange)
{
if (exchange->handler == NULL) {
return;
}
if (exchange->type != MSG_ACK) {
return;
}
//直接调用响应处理函数处理
exchange->handler(&exchange->request, &exchange->response);
}
处理MSG_DIRECT类型的消息
//当消息类型为MSG_DIRECT时,执行响应处理函数
static void ProcDirectRequest(Exchange *exchange)
{
if (exchange->handler == NULL) {
return;
}
if (exchange->type != MSG_DIRECT) {
return;
}
//直接调用响应处理函数处理
exchange->handler(&exchange->request, &exchange->response);
}
更新exchange对象所属的服务实例
//返回当前exchange对象对应的ServiceImpl
static ServiceImpl *CorrectServiceImpl(Exchange *exchange, ServiceImpl *serviceImpl)
{
if (exchange->type == MSG_ACK) {
//ack消息使用最后一个服务,不需要修改
return serviceImpl;
}
if (serviceImpl == NULL || serviceImpl->serviceId != exchange->id.serviceId) {
//根据serviceId获取新的serviceImpl
serviceImpl = SAMGR_GetServiceByID(exchange->id.serviceId);
}
if (serviceImpl == NULL) {
return NULL;
}
return serviceImpl;
}
获取当前线程的私有变量,存储的值是消息队列ID
//获取当前线程绑定的消息队列的ID
MQueueId SAMGR_GetCurrentQueueID()
{
//取出当前线程存储在g_localKey中的值,即当前线程对应的消息队列ID
return (MQueueId)THREAD_GetThreadLocal();
}
服务开始处理消息
//开始处理消息,更新ServiceImpl的消息处理数和时间戳,并更改状态为SVC_BUSY
static void BeginWork(ServiceImpl *service)
{
if (service == NULL || service->inited != SVC_IDLE) {//疑惑!若当前服务状态为繁忙,从这里return后,下面的消息记录和时间戳更新都不会执行,那么会导致实际处理的消息数大于记录的消息数
//service为NULL 或者service的状态不为闲置,则返回
return;
}
if (service->ops.step == BOOT_SYS_WAIT) {
WDT_Start(MSG_PROC_THRESHOLD);
}
//更新service所处理的消息数
service->ops.messages++;
//更新处理消息的时间戳
service->ops.timestamp = SAMGR_GetProcessTime();
//更新服务状态为繁忙,表示当前服务正在处理
service->inited = SVC_BUSY;
}
服务处理消息结束
//结束处理消息,判断处理消息的时间间隔是否超出阈值,若超出需增加异常数并记录日志。最后更新状态为SVC_IDLE
static void EndWork(ServiceImpl *service, const Exchange *exchange)
{
if (service == NULL || service->inited != SVC_BUSY) {
return;
}
if (service->ops.step == BOOT_SYS_WAIT) {
WDT_Stop();
}
//处理的最后一条消息的时间
uint32 lastTime = service->ops.timestamp;
//当前时间
service->ops.timestamp = (uint32)SAMGR_GetProcessTime();
//时间间隔
uint32 interval = GET_INTERVAL(lastTime, service->ops.timestamp);
if (interval > MSG_PROC_THRESHOLD) {
//消息超时
const char *name = service->service->GetName(service->service);
HILOG_INFO(HILOG_MODULE_SAMGR, "Message Timeout <service:%s, feature:%d, type:%d, reqId:%d, time:%ums>",
name, exchange->id.featureId, exchange->type, exchange->request.msgId, interval);
//异常情况+1
service->ops.abnormal++;
}
//更新service的状态为SVC_IDLE
service->inited = SVC_IDLE;
}
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请看下图提示: