学习记录:共享内存实现
共享内存类,头文件:
#include <Windows.h>
#include <iostream>
#include <vector>
typedef struct ChunkInfo
{
int read; //读的位置,为了确定读那一块儿的区域,必须在首端设置一个读的指针(写的也应该)
int write;
int chunksize[8]; //还可以有其他的信息(这里写了每个块写入的区域size)
}ChunkInfo;
#define ShareMemoryLen 8//一共8块区域,使用循环数组进行遍历读取
#define ShareMemorySize 1920*1080*3*8*8+sizeof(ChunkInfo) //8块1920*1080*3*8大小的内存写入区域
#define ShareMemoryName L"ShareMemoryName"
using std::vector;
class ShareMemory
{
public:
ShareMemory(bool bval);//判断是创建的还是非创建
void Init(int size=0);
bool Read(int &size,uint8_t* ch);
bool Write(int &size, uint8_t* ch);
private:
int m_size;
void* m_buffer;
bool m_isCreate;
};
函数实现:
#include "ShareMemory.h"
ShareMemory::ShareMemory(bool bval)
:m_isCreate(bval)//共享内存创建相同名字只能有一个(一个创建剩下的来读取)
{
}
void ShareMemory::Init(int size=0)//进行初始化
{
if (size == 0)
m_size = ShareMemorySize;
if (m_isCreate)//创建共享内存
{
//创建成功,返回创建的内存映射文件的句柄
HANDLE handle = CreateFileMapping( //创建内存映射文件的内核对象
INVALID_HANDLE_VALUE, //文件句柄,默认
NULL, //安全描述符,没有写null(可以用安全描述符来指定什么类型的程序(例如:system,server,user)可以访问该共享内存)
PAGE_READWRITE, //映射对象类型
0, //文件映射最大长度的高32位
m_size, //文件映射最大长度的低32位
ShareMemoryName //文件映射对象的名称
);
if (handle)
{
//通过创建返回的句柄将内存映射文件映射到进程的虚拟地址中(返回共享内存起始地址)
m_buffer = (void*)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, m_size);
}
}
else
{
HANDLE handle = OpenFileMapping( //如果已经创建好了,就直接打开独影的内存映射对象
FILE_MAP_READ | FILE_MAP_WRITE, //数据的访问方式
FALSE, //是否继承句柄
ShareMemoryName //文件映射对象名称
);
if (handle)
{
m_buffer = (void*)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, m_size);
}
}
ChunkInfo* chunkinfo = (ChunkInfo*)m_buffer;
chunkinfo->read = 0;
chunkinfo->write = 0;
for (int i = 0; i < 8; ++i)
chunkinfo->chunksize[i] = -1;
}
bool ShareMemory::Read(int &size, uint8_t* ch)
{
ChunkInfo* chunkinfo = (ChunkInfo*)m_buffer;
int pread = chunkinfo->read;
int pwrite = chunkinfo->write;
//判断循环队列是否为空
if (pread == pwrite)
{
std::cout << "共享内存为空,读取失败" << std::endl;
return false;
}
else
{
size = chunkinfo->chunksize[chunkinfo->read];
if (size < 0)
return false;
chunkinfo->read = (chunkinfo->read + 1) % ShareMemoryLen;
size_t pos = (m_size - sizeof(ChunkInfo)) / ShareMemoryLen * (chunkinfo->read);//求得 除去共享内存中数据头的相对位置
//找到读取的起始位置
uint8_t* ptrRead = (uint8_t*)m_buffer + sizeof(ChunkInfo) + pos;
if (0 == memcpy_s(ptrRead, size, ch, size))//赋值
{
std::cout << "read success" << std::endl;
return true;
}
else
{
std::cout << "read fail" << std::endl;
return false;
}
}
}
bool ShareMemory::Write(int& size, uint8_t* ch)
{
ChunkInfo* chunkinfo = (ChunkInfo*)m_buffer;
if ((chunkinfo->read + 1) % 8 == chunkinfo->write) //循环队列,牺牲一个空间来判断满
{
std::cout << "共享内存已满,写入失败" << std::endl;
return false;
}
else
{
chunkinfo->chunksize[chunkinfo->write] = size;
chunkinfo->write = (chunkinfo->write + 1) % ShareMemoryLen;
size_t pos = (m_size - sizeof(ChunkInfo)) / ShareMemoryLen * chunkinfo->write;
uint8_t* ptrWrite = (uint8_t*)m_buffer + pos + sizeof(ChunkInfo);
if (0 == memcpy_s(ch, size, ptrWrite, size))
{
std::cout << "write success" << std::endl;
return true;
}
else
{
std::cout << "write success" << std::endl;
return false;
}
}
}