liteos定时器回调时间过长造成死机问题解决思路

项目需求

原代码是稳定的,现我实现EMQ平台断开连接的时候,把HSL的模拟点位数据采集到网关,然后存入Flash,当EMQ平台连接的时候,把Flash里面的点位数据放在消息队列里面,不影响实时采集。

核心1:EMQ平台断开,保持存储稳定

核心2:不影响实时采集的前提下去把flash的数据读出来在空闲的时候发出去

核心3:进入断点续传的条件是连续5次发布失败进入断点续传

问题描述

核心1遇到了问题,就是EMQ断开20分钟左右会死机,没日志输出。

最后的日志,然后就一直在进行度队列操作,队列ID是垃圾值

初步分析

1.队列可能在使用的时候没有创建

2.队列的id存的地方被覆盖了

c 复制代码
[2024-07-24 17:20:49.179]# RECV ASCII>
[INFO][556][Plc_s7_Task:1404] RDataCnt:30,RWarnCnt:0 CDataCnt:30,CWarnCnt:0 Tol:30,elaps: 251ms
[INFO][556][getNetSignalValue:1037] EC20 Get Net Signle: "25"
[INFO][556][print_memory_usage:594] m_aucSysMem0      2000d4f8 Memory Used:5992, Free:135072, Tol:141064, MallocCnt: 21082, FreeCnt: 20964, Malloc-Free: 118
[WARN]osSwTmrTask:111 timer_handler(080540fd) cost too many ms(5995)


代码

c 复制代码
void point_timer_Callback(UINT32 arg)
{
	UINT32 uwReportRet = LOS_OK;
	UINT32 uwCollectRet = LOS_OK;
	uint16_t ep_resources[] = {RESOURCES_STATUS};
	char buff[64] = {0};
	char *buf[1] = {buff};

	LOS_SwtmrStop(point_pusSwTmrID);

    // 反写任务正在执行,跳过本次检查
    if (g_reverse_write_processing == true) {
//		 if (g_reverse_write_processing == true) {	
        //重新开启定时器,准备下一次检查
	    LOS_SwtmrStart(point_pusSwTmrID);
        return;
    }

	if (!Get_Point_Status())
	{
		LOS_SwtmrStart(point_pusSwTmrID);	
		return;
	}

	//启动上报任务
	uwReportRet = start_report_task();
	if(LOS_OK != uwReportRet)
	{	
		ATINY_LOG(LOG_ERR, "start_report_task Error!");
		stop_report_task();
	}

	//启动采集任务
	uwCollectRet = start_collect_task();
	if (LOS_OK != uwCollectRet)
	{
		ATINY_LOG(LOG_ERR, "start_collect_task Error!");
		stop_collect_task();
	}

	if (LOS_OK != uwCollectRet || LOS_OK != uwReportRet)
	{
		//检查是否绑定
		if(0 == read_resoures(LWM2M_EP_OBJECT_ID, 0, ep_resources, buf, 1, RESOURCES_POINT_SAVE_STRING_MAX))
		{
			if(0 == atoi(buf[0]))
			{
				ATINY_LOG(LOG_INFO, "Wait Bing!");
			}
			else
			{
				ATINY_LOG(LOG_INFO, "Restart Report || Collect!");
			}
		}
		else
		{
			ATINY_LOG(LOG_ERR, "File System Error, Need Clean Config & Restart!");
		}
	}

	//检查系统异常
	//TODO:是否应该独立为一个检测线程,但上报通道依赖mqtt,mqtt又和数据点采集耦合在一起。应先解耦mqtt和数据采集
	if(LOS_OK == check_report_task())
	{
		check_sys_warning();
	}

    south_report_gateway();

	print_memory_usage();

	//重新开启定时器,准备下一次检查
	LOS_SwtmrStart(point_pusSwTmrID);	
}

解决方法

080540fd 地址定位到回调函数是void point_timer_Callback(UINT32 arg)

根据日志知道是这个回调时间有点长。

那为啥不是立即死而是过了几十分钟死呢?

代码优化等级从2调为0,进一步调试

c 复制代码
LOS_SwtmrStop(point_pusSwTmrID);

他知道他自己耗时还在函数这里把定时器关了,怒。那为啥会调试的时候死在读队列(队列操作)里面呢?因为定时器的回调函数其实都是存在定时器回调队列里面的,如果一个回调过长,因为定时器的回调优先级0,其他高优先级任务都执行不下去。在实时性操作系统里会紊乱系统,加上屎山代码,就会死机。所以在liteos这种系统里面,多加日志输出,不可完全信调试。调试只是一瞬间的观察,调试可以判断这一段时间进而想一下自己的改动点和日志做分析得出怀疑点。

上面判断条件

c 复制代码
if (g_reverse_write_processing == true )

改为

c 复制代码
if (g_reverse_write_processing == true || BreakPoint_State == BreakPointSaveOnline)

OK,不要动不动在回调函数写耗时操作,一两次可能没问题,但是一直进行回调的话,会造成奇怪的紊乱。

相关推荐
爱浦路 IPLOOK3 分钟前
选对UPF网元供应商,解锁5G-A时代行业赋能新可能
运维·网络·数据库
Elastic 中国社区官方博客13 分钟前
将 Logstash 管道从 Azure Event Hubs 迁移到 Kafka 输入插件
大数据·数据库·elasticsearch·microsoft·搜索引擎·kafka·azure
草莓熊Lotso14 分钟前
MySQL 事务管理全解:从 ACID 特性、隔离级别到 MVCC 底层原理
linux·运维·服务器·c语言·数据库·c++·mysql
鸽芷咕19 分钟前
Oracle 替代工程实践深度解析:金仓全链路工程实践 —— 从评估决策到平滑上线的深度技术攻坚
数据库·oracle
gushinghsjj33 分钟前
元数据管理包含哪些?元数据管理如何支持数据分析?
数据库·oracle·数据分析
不愿透露姓名的大鹏38 分钟前
MySQL InnoDB核心参数深度优化/性能调优
运维·服务器·数据库·mysql
heimeiyingwang42 分钟前
【架构实战】图数据库Neo4j在社交系统中的应用
数据库·架构·neo4j
夕除1 小时前
MVN--06
数据库·sql·mybatis
鸠摩智首席音效师1 小时前
如何在 MacOS 上安装 PostgreSQL ?
数据库·macos·postgresql