最近开发Zynq视频处理项目,视频通路通过VDMA导通并一系列处理。PS端,在petalinux+SDK开发应用程序,使用了opencv的最基础的imwrite,试想通过指令响应来保存当前视频中的图片到存储介质(SD、eMMC)
初期语句很简短,1)给出文件路径+名称,2)检查有无同名文件,3)无同名文件时,则imwrite图片mat到路径,mat中的data指针映射到DDR中VDMA接收图像地址。如下:
常规定义文件操作函数:
inline bool file_exist_chk(const std::string& name)
{
return ( access( name.c_str(), F_OK ) != -1 );
}
inline bool file_delete(const std::string& name)
{
return ( remove( name.c_str() ) != -1 );
}
inline bool file_rename(const std::string& src_name, const std::string& dst_name)
{
return ( rename( src_name.c_str(),dst_name.c_str() ) != -1 );
}
main函数中while循环中,满足调节后执行下述图片写文件操作
if【满足条件】
{
string add_name = "/media/TMP_";
string add_num = to_string(k);
add_name += add_num;
add_name += ".bmp";
if(file_exist_chk(add_name)==0)
{
imwrite(add_name, im_pic);
printf("add template success\n");
}
}
问题一:遇到问题是,当反复发指令保存图片,频繁操作一通之后(720p图像约50张存储以后),明显出现内存泄漏的现象,未分配的地址明显被异常改写,甚至改写到了VDMA显示读取地址段。随着继续反复操作imwrite,内存泄漏严重到导致linux系统崩溃。
经参考下面帖子:imwrite导致linux内存泄漏有类似案例
解决办法如下帖子:
https://www.tecmint.com/clear-ram-memory-cache-buffer-and-swap-space-on-linux/
总结就是使用system("sync; echo 1 > /proc/sys/vm/drop_caches");定期清理cache来解决imwrite导致的内存泄漏问题。
修改后的代码如下:
{
string add_name = "/media/TMP_";
string add_num = to_string(k);
add_name += add_num;
add_name += ".bmp";
if(file_exist_chk(add_name)==0)
{
system("sync; echo 1 > /proc/sys/vm/drop_caches");
imwrite(add_name, im_pic);
printf("add template success\n");
}
}
经修改后,代码可以经受住反复频繁写入拷机测试,测试上千次保存图片系统不再崩溃。
问题二:
进而(1)有一个需求imwrite有覆盖同名文件写入的任务,(2)同时有在主while循环中有发送串口输出一串命令的任务。二者任务一前一后执行,逻辑上没有冲突,也没有开辟独立线程分别执行,很单纯的执行完文件存储之后发送串口。
但现象出现当imwrite同名覆盖条件出现时,串口向外发出的一串命令偶发性的不完整。概率约10%。连续重复同名覆盖imwrite操作,必然会复现问题。说明和imwrite同名覆盖有关。
解决办法:覆盖操作时使用imwrite前,先check文件名是否同名,同名的话先删除,后再写入。
{
add_name = "/media/TMP_";
add_num = to_string(loop_num);
add_name += add_num;
add_name += ".bmp";
if(file_exist_chk(add_name)==1)//如果同名
{
if(file_delete(add_name))//先删除原文件名
{
printf("Delete Template[%d] Success!\n",id_template);
system("sync; echo 1 > /proc/sys/vm/drop_caches");
imwrite(add_name, im_pic);//再常规写入
}
}
}