//头文件
#include <sys/mman.h>
#include <sys/stat.h>
#include <memory>
#include <atomic>
#include <slam/SlamMapUpdateRange.h>
//1.共享内存结构体定义
#define MEMORY_SIZE 100 << 20 //内存预留100MB
struct MapSharedMemory
{
std::atomic<bool> is_busy_; //空闲标志位
int size_x; //地图长
int size_y; //地图宽
int8_t map_data[MEMORY_SIZE]; //地图内存
};
//2.初始化共享内存
bool OpenSharedMemory() //初始化成功后/dev/shm/目录下会出现map_share_mem,大小应该等于sizeof(MapSharedMemory)
{
shareId = shm_open("/map_share_mem", O_CREAT|O_RDWR|O_EXCL, 0777);
if(shareId < 0)
{
shareId = shm_open("/map_share_mem", O_RDWR, 0777);
}else
{
ftruncate(shareId, sizeof(MapSharedMemory));
}
if (shareId >= 0)
{
shm_ptr = (MapSharedMemory*)mmap(NULL, sizeof(MapSharedMemory), PROT_READ|PROT_WRITE, MAP_SHARED, this->shareId, 0);
}
if (shm_ptr != nullptr)
{
shm_ptr->is_busy_ = false;
return true;
}
return false;
}
//3.更新地图,
订阅 topic: "slam/SlamMapUpdateRange".
topic 类型为: slam::SlamMapUpdateRange
在回调中激活地图更新
void CopyShareMemoryThread(const slam::SlamMapUpdateRange::ConstPtr& msg)
{
if(!this->shm_ptr->is_busy_.exchange(true)) // 确保其他进程没有在写入或读取共享内存
{
if (msg->x_max - msg->x_min + 1 == shm_ptr->size_x && msg->y_max - msg->y_min + 1 == shm_ptr->size_y) // 整图更新(10000x10000 约50ms)
{
const int copy_size = shm_ptr->size_x * shm_ptr->size_y;
std::memcpy(&slam_map_data_[0], shm_ptr->map_data, copy_size);
}
else // 局部更新(一般<5ms)
{
for (int x(msg->x_min); x <= msg->x_max; x++)
{
const int offset(x * shm_ptr->size_y + msg->y_min);
const int copy_size(msg->y_max - msg->y_min + 1);
std::memcpy(&slam_map_data_[offset], shm_ptr->map_data + offset, copy_size);
}
}
shm_ptr->is_busy_ = false;
}
}
sharedMemory.h
/*
* sharedMemory.h
*
* Created on: 2020��7��29��
* Author: wayne.shen
*/
#ifndef SRC_MEDUSA_PLUGIN_OBJECTDETECTOR_SHAREDMEMORY_H_
#define SRC_MEDUSA_PLUGIN_OBJECTDETECTOR_SHAREDMEMORY_H_
#ifdef __cplusplus
extern "C"{
#endif
#include "mds_media.h"
typedef struct sharedMemory SharedImage;
int updateSharedImage(MdsImgBuf *imageBuf , void *ptr , int size , SharedImage* sharedAddr);
SharedImage *initSharedMemory(char *memoryFile);
#ifdef __cplusplus
}
#endif
#endif /* SRC_MEDUSA_PLUGIN_OBJECTDETECTOR_SHAREDMEMORY_H_ */
sharedMemory.cpp
/*
* sharedMemory.cpp
*
* Created on: 2020��7��29��
* Author: wayne.shen
*/
#define _DEBUG_
#include <EcoLog.h>
#include "sharedMemory.h"
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <memory>
#include <string.h>
#include <atomic>
struct sharedMemory{
std::atomic<bool> isUsing;
std::atomic<bool> isUpdated;
MdsPixFmt pixFmt;
long int ts;
double isp_exposure;
double isp_gain;
int bufSize;
int width;
int height;
char imageData[2000000];
};
static int sharedFd;
SharedImage *initSharedMemory(char *memoryFile)
{
SharedImage *sharedAddr = NULL;
sharedFd = shm_open(memoryFile , O_CREAT|O_RDWR|O_EXCL, 0777);
if(sharedFd < 0)
{
sharedFd = shm_open(memoryFile , O_RDWR, 0777);
}else
{
ftruncate(sharedFd, sizeof(SharedImage));
}
if(sharedFd >= 0)
{
void *shm = mmap(NULL , sizeof(SharedImage) , PROT_READ|PROT_WRITE, MAP_SHARED, sharedFd , 0);
close(sharedFd);
if(shm != NULL)
{
sharedAddr = (SharedImage *)shm;
sharedAddr->isUsing = false;
sharedAddr->isUpdated = false;
}
}
ECO_LOGL("shared memory:%p\n" , sharedAddr);
return sharedAddr;
}
void OpenSharedMemory()
{
shm_ptr = nullptr;
shareId = shm_open("/map_share_mem", O_CREAT|O_RDWR|O_EXCL, 0777);
if(shareId < 0)
{
shareId = shm_open("/map_share_mem", O_RDWR, 0777);
}else
{
ftruncate(shareId, sizeof(MapSharedMamory));
}
if (shareId >= 0)
{
shm_ptr = (MapSharedMamory*)mmap(NULL, sizeof(MapSharedMamory), PROT_READ|PROT_WRITE, MAP_SHARED, this->shareId, 0);
close(shareId);
if (shm_ptr != nullptr)
{
shm_ptr->is_busy_ = false;
}
}
}
int updateSharedImage(MdsImgBuf *imageBuf , void *ptr , int size , SharedImage *sharedAddr)
{
if(!sharedAddr->isUsing.exchange(true) )
{
ECO_LOGL("update memory:%lld %p %d %d %d\n" ,imageBuf->ts , sharedAddr , size , imageBuf->width , imageBuf->height);
sharedAddr->pixFmt = imageBuf->pixFmt;
sharedAddr->ts = imageBuf->ts;
sharedAddr->isp_exposure = imageBuf->isp_exposure;
sharedAddr->isp_gain = imageBuf->isp_gain;
sharedAddr->bufSize = size;
sharedAddr->width = imageBuf->width;
sharedAddr->height = imageBuf->height;
memcpy(sharedAddr->imageData , ptr , size);
sharedAddr->isUpdated = true;
sharedAddr->isUsing = false;
}
return 0;
}
void detectSharedMemory()
{
if(this->sharedAddr == NULL)
return ;
// 设置使用中标志,防止发送端在使用时修改内容。
if(!this->sharedAddr->isUsing.exchange(true))
{
// this->sharedAddr->isUsing = 1;
if(this->sharedAddr->isUpdated)
{
// todo 处理数据程序
ECO_LOGL("detect memory:%d\n" , this->sharedAddr->bufSize);
// 处理数据后设置更新标志位
this->sharedAddr->isUpdated = false;
}
// 修改处理后使用中标志位释放使用权
this->sharedAddr->isUsing = false;
}
}