在freeRTOS中的内存泄漏问题
1、情景描述:
在我的某个STM32项目当中,同时有三个采集任务在采集不同的传感器,采集到一定数量,就会通过消息队列的方式将数据传递到发送任务当中,发送任务接收后将数据写入到SD卡当中。传递的数据结构体如下所示:(暂且叫采集任务为TX,发送任务为RX,这里的TXRX是相对消息队列的走向而言)
typedef struct {
uint8_t * data;
uint32_t len;
}data_struct;
显然,我传的是一个名为data的指针,所以需要在TX当中申请一片内存,接着在RX中处理并释放。
//TX采集任务
while(1)
{
......
//申请内存
msg_sd.data = pvPortMalloc(len_of_send);
//写队列
osStatus_t status_SD = osMessageQueuePut(SDquereHandle, &msg_sd, 0, osWaitForever);
}
//RX发送任务
//获取SD卡状态
while(1)
{
......
//读队列
osStatus_t status = osMessageQueueGet(SDquereHandle, &msg, NULL, osWaitForever);
//写SD卡
SDwrite(xxxx);
//释放
vPortFree(msg.data); // 释放内存
......
}
已知我的堆内存大约是20000字节,且RX的任务优先级高于所有的采集任务TX。所以理论上来说这样子做是不会有什么问题的。
但是实际上,当我运行了7到8个小时后,我的堆内存会在某个时间点断崖式下降。
2、分析
(一)是否存在持续的内存泄漏
显然,断崖式下降并不是长时间的泄漏引起的,所以排除。
(二)是否是释放不及时导致
从现象来看,确实可能是释放不及时,因为在RX中做了文件读写的操作,在7到8个小时连续读写的情况下,文件大小也到了600M左右,文件越大,写入的时间越长。那么在文件写入的函数(f_write)中阻塞的时间就越长。而在freeRTOS中,文件写入的阻塞是指挂起当前的任务,也就是挂起当前的发送任务,这时我们的采集任务就可以继续运行了,如果在这段时间内,采集任务又向消息队列中加入数据,而我们的发送任务来不及释放就会造成内存泄漏。
3、解决方法
文件写入到一定大小就创建一个新的文件继续写入,保证写消息队列的数据小于读消息队列的数据,这样内存就不会泄漏了。