版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gao271003105/article/details/85257422
32位进程无论打开还是创建共享内存,都不能超过2G,否则会报〖8〗-存储空间不足,无法处理此命令。
那么如何在32位进程使用超过2G的共享内存呢?
答案是使用64位进程开启共享内存,没有2G的限制,也没有4G的限制,放心大胆的开。
然后32位进程再打开这部分共享内存,前面说不能打开超过2G,这里我们就把64位进程开启的这一片共享内存分成很多个小块,例如每一块10M一共410块,这样差不多4G了。而32位进程每次使用的时候只需要打开10M的共享内存读写,大于10M了则关闭当前的共享内存,再打开下一块。
那么如何循环读写这片4G共享内存呢,答案是环形共享内存,也就是读到末尾从头再来。
中间有个小插曲,无法写入其他进程开启的共享内存,报〖5〗-拒绝访问。后来试验出是因为打开权限不够,改成如下两句就可以了,(都是用FILE_MAP_ALL_ACCESS)
OpenFileMapping(FILE_MAP_ALL_ACCESS, false, name)
MapViewOfFile(sharedMemoryInfo.sharedMemoryHandle.m_FileMapping, FILE_MAP_ALL_ACCESS, 0,0,length);
一、先讲64开共享内存,贴一个被用无数遍的C#类(稍微改动了一下),C++可以照着翻译过去。
使用这个类来创建多块共享内存
public class ShareMemoryHelper
{
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
[DllImport("kernel32", EntryPoint = "GetLastError")]
public static extern int GetLastError();
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
public IntPtr fileMapping = IntPtr.Zero;
public IntPtr mapView = IntPtr.Zero;
const int FILE_MAP_COPY = 0x0001;
const int FILE_MAP_WRITE = 0x0002;
const int FILE_MAP_READ = 0x0004;
const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004;
const int PAGE_READWRITE = 0x04;
const int INVALID_HANDLE_VALUE = -1;
const int ERROR_ALREADY_EXISTS = 183;
private bool bValid;
bool m_bAlreadyExist = false;
bool m_bInit = false;
long m_MemSize = 0;
public ShareMemoryHelper(string name, uint length)
{
bValid = GetShareMemoryMap(name, length);
}
public ShareMemoryHelper()
{
}
~ShareMemoryHelper()
{
Close();
}
public bool GetShareMemoryMap(string name, uint length)
{
m_MemSize = length;
fileMapping = OpenFileMapping(PAGE_READWRITE, false, name);
if (fileMapping == IntPtr.Zero)
{
return false;
}
mapView = MapViewOfFile(fileMapping, (uint)FILE_MAP_READ, 0, 0, length);
if (mapView == IntPtr.Zero)
{
int a = GetLastError();
return false;
}
m_bInit = true;
return true;
}
public int CreateShareMemoryMap(string strName, long lngSize)
{
//if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000;
m_MemSize = lngSize;
if (strName.Length > 0)
{
fileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)lngSize, strName);
if (fileMapping == IntPtr.Zero)
{
return 2;
}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
m_bAlreadyExist = true;
}
else
{
m_bAlreadyExist = false;
}
mapView = MapViewOfFile(fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, (uint)lngSize);
if (mapView == IntPtr.Zero)
{
m_bInit = false;
CloseHandle(fileMapping);
return 3;
}
else
{
m_bInit = true;
if (m_bAlreadyExist == false)
{
}
}
}
else
{
return 1;
}
return 0;
}
public int Write(byte[] bytData, int lngAddr, int lngSize)
{
if (lngAddr + lngSize > m_MemSize) return 2;
if (m_bInit)
{
Marshal.Copy(bytData, lngAddr, mapView, lngSize);
}
else
{
return 1;
}
return 0;
}
public int Read(ref byte[] bytData, int lngAddr, int lngSize)
{
if (lngAddr + lngSize > m_MemSize) return 2;
if (m_bInit)
{
Marshal.Copy(mapView, bytData, lngAddr, lngSize);
}
else
{
return 1;
}
return 0;
}
/// <summary>
///
/// </summary>
/// <param name="bytData">destination</param>
/// <param name="lngAddr">sourse start index</param>
/// <param name="lngSize">copy length</param>
/// <returns></returns>
public int Read2(ref byte[] bytData, int lngAddr, int lngSize)
{
if (lngAddr + lngSize > m_MemSize) return 2;
if (m_bInit)
{
Marshal.Copy(mapView + lngAddr, bytData, 0, lngSize);
}
else
{
return 1;
}
return 0;
}
public void Close()
{
if (m_bInit)
{
UnmapViewOfFile(mapView);
CloseHandle(fileMapping);
}
}
}
二、32位C++环形读写这片共享内存
头文件和源文件如下,这个是客户,只管读写
#pragma once
#include <vector>
#include "ShareMemoryManager.h"
class ShareMemoryHelper
{
public:
ShareMemoryHelper();
virtual ~ShareMemoryHelper();
private:
std::vector<DataBlock> ValidDataVector;
public:
void PushShareMemory(std::vector< unsigned __int8>& data);
bool FrontShareMemory(std::vector< unsigned __int8>& data);
};
#include "precompiled.h"
#include <iterator>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include "ShareMemoryHelper.h"
ShareMemoryHelper::ShareMemoryHelper()
{
GetModuleEx().LogMsg( LogLevel::Info, Sys::RECONCTRL_NAME, "new reconjob", Err::EMPTY,
__FILE__, __LINE__, __TIMESTAMP__);
}
ShareMemoryHelper::~ShareMemoryHelper()
{
}
bool ShareMemoryHelper::FrontShareMemory(std::vector< unsigned __int8> &data)
{
vector<DataBlock>::iterator iter = ValidDataVector.begin();
ShareMemoryManager::GetInstance()->FrontShareMemory(iter, data);
ValidDataVector.erase(iter);
return true;
}
void ShareMemoryHelper::PushShareMemory(std::vector< unsigned __int8>& data)
{
DataBlock mDataBlock= ShareMemoryManager::GetInstance()->PushShareMemory(data);
mDataBlock.size = data.size();
ValidDataVector.push_back(mDataBlock);//mapping reconjob
}
下面这个是读写的管理者,决定往哪里写,从哪里读。考虑了写的数据大于分配的最小共内存单元
头文件和源文件如下
#pragma once
#include <vector>
struct HugeNumber
{
int x;//int max
int y;
};
struct DataBlock
{
int size;
HugeNumber head;
HugeNumber tail;
};
struct SharedMemoryHandle
{
SharedMemoryHandle()
{
m_FileMapping = 0;
m_MapView = NULL;
}
HANDLE m_FileMapping;
void* m_MapView;
};
struct SharedMemoryInfo
{
HugeNumber CircularInfo;
CString sharedMemoryName;
SharedMemoryHandle sharedMemoryHandle;
};
class ShareMemoryManager
{
public:
virtual ~ShareMemoryManager();
private:
ShareMemoryManager();
CString m_Main_SMName;
int nMaxBufferList;//Buffer List count
unsigned m_Main_SMLength;//max length of Main area
std::vector<DataBlock> DataBlockHeadInfoList;
std::vector<CString> m_Main_DataSMNameList;//remember sharememory name
int Init();
void CloseSharedMemory(SharedMemoryHandle& sharedMemoryHandle);
DataBlock WriteSharedMemory(const unsigned char* data, int length);
int OpenShareMemory(SharedMemoryInfo &sharedMemoryInfo, CString name, int length);
SharedMemoryInfo CircularHeadSMI;//remember head sharememory info point
SharedMemoryInfo CircularTailSMI;//remember tail sharememory info point
bool GetCircularHeadSMI(int index);
bool GetNextCircularTailSMI();
HugeNumber GetCircularLength();
bool CheckRestSpace(int needLength);
public:
DataBlock PushShareMemory(std::vector< unsigned __int8>& data);
bool FrontShareMemory(vector<DataBlock>::iterator &ReadDataBlockInfo, std::vector< unsigned __int8> &data);
static ShareMemoryManager* GetInstance();
};
#include "precompiled.h"
#include <iterator>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <assert.h>
#include "ShareMemoryHelper.h"
ShareMemoryManager::ShareMemoryManager()
{
Init();
}
static ShareMemoryManager *m_pInstance;
static HANDLE m_hMutexInstance;
ShareMemoryManager* ShareMemoryManager::GetInstance()
{
if (nullptr == m_pInstance)
{
m_hMutexInstance = CreateMutex(NULL, FALSE, LPCSTR("instance"));//mutex
WaitForSingleObject(m_hMutexInstance, INFINITE);
if (nullptr == m_pInstance)
{
m_pInstance = new ShareMemoryManager();
}
ReleaseMutex(m_hMutexInstance);
}
return m_pInstance;
}
ShareMemoryManager::~ShareMemoryManager()
{
CloseSharedMemory(CircularHeadSMI.sharedMemoryHandle);
CloseSharedMemory(CircularTailSMI.sharedMemoryHandle);
}
void ShareMemoryManager::CloseSharedMemory(SharedMemoryHandle& sharedMemoryHandle)
{
UnmapViewOfFile(sharedMemoryHandle.m_MapView);
sharedMemoryHandle.m_MapView = NULL;
CloseHandle(sharedMemoryHandle.m_FileMapping);
sharedMemoryHandle.m_FileMapping = 0;
}
int ShareMemoryManager::Init()
{
nMaxBufferList = 410;
m_Main_SMLength = 10485760);//10M
m_Main_SMName = "Global\\DataMapFileMain";
for (int i = 0; i < nMaxBufferList; i++)
{
CString postfix;
postfix.Format("%d", i);
m_Main_DataSMNameList.push_back(m_Main_SMName + postfix);
}
if (-1 == OpenShareMemory(CircularHeadSMI, m_Main_DataSMNameList[0], m_Main_SMLength))
{
return -3;
}
CircularHeadSMI.CircularInfo.x = 0;
CircularHeadSMI.CircularInfo.y = -1;
if (-1 == OpenShareMemory(CircularTailSMI, m_Main_DataSMNameList[0], m_Main_SMLength))
{
return -3;
}
CircularTailSMI.CircularInfo.x = 0;
CircularTailSMI.CircularInfo.y = -1;
return 1;
}
int ShareMemoryManager::OpenShareMemory(SharedMemoryInfo &sharedMemoryInfo, CString name, int length)
{
sharedMemoryInfo.sharedMemoryName = name;
sharedMemoryInfo.sharedMemoryHandle.m_FileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, name);
if (NULL == sharedMemoryInfo.sharedMemoryHandle.m_FileMapping)
{
CString error;
error.Format("%d", GetLastError());
return -1;
}
sharedMemoryInfo.sharedMemoryHandle.m_MapView = MapViewOfFile(sharedMemoryInfo.sharedMemoryHandle.m_FileMapping, FILE_MAP_ALL_ACCESS, 0,0,length); // map all file
if (NULL == sharedMemoryInfo.sharedMemoryHandle.m_MapView)
{
CString errorm;
errorm.Format("%d", GetLastError());
return -1;
}
return 1;
}
bool cmp(DataBlock a, DataBlock b){
if(a.head.x==b.head.x && a.tail.x==b.tail.x &&
a.head.y==b.head.y && a.tail.y==b.tail.y)
return true;
return false;
}
bool ShareMemoryManager::FrontShareMemory(vector<DataBlock>::iterator &ReadDataBlockInfo, std::vector< unsigned __int8> &data)
{
if(ReadDataBlockInfo->head.x == ReadDataBlockInfo->tail.x)//all data in one sharememory
{
if (!GetCircularHeadSMI(ReadDataBlockInfo->head.x))
{
return false;
}
char* mReadPtr = (char*)CircularHeadSMI.sharedMemoryHandle.m_MapView;
int size = ReadDataBlockInfo->size;
//int size = ReadDataBlockInfo->tail.y - ReadDataBlockInfo->head.y + 1;
data.resize(size);
memcpy((char*)&data[0], mReadPtr + ReadDataBlockInfo->head.y, size * sizeof(__int8));
}
else
{
int count = (ReadDataBlockInfo->tail.x - ReadDataBlockInfo->head.x + nMaxBufferList) % nMaxBufferList + 1;
data.resize(ReadDataBlockInfo->size);
int writeLength = 0;
for (int i = 0; i < count; i++)
{
int readLength = (i == count -1) ? ReadDataBlockInfo->tail.y + 1:
(i == 0) ? m_Main_SMLength - ReadDataBlockInfo->head.y : m_Main_SMLength;
if (!GetCircularHeadSMI((ReadDataBlockInfo->head.x + i) % nMaxBufferList ))
{
return false;
}
char* mReadPtr = (char*)CircularHeadSMI.sharedMemoryHandle.m_MapView;
memcpy((char*)&data[writeLength], mReadPtr + ((i == 0) ? ReadDataBlockInfo->head.y : 0), readLength * sizeof(__int8));
writeLength += readLength;
}
}
//updata CircularHead
if(m_Main_SMLength - 1 == ReadDataBlockInfo->tail.y)//last index
{
GetCircularHeadSMI((ReadDataBlockInfo->tail.x + 1) % nMaxBufferList);
}
else
{
CircularHeadSMI.CircularInfo.x = ReadDataBlockInfo->tail.x;
CircularHeadSMI.CircularInfo.y = ReadDataBlockInfo->tail.y + 1;
}
vector<DataBlock>::iterator s=find_if(DataBlockHeadInfoList.begin(), DataBlockHeadInfoList.end(),
[&ReadDataBlockInfo](DataBlock const & obj) {return obj.head.x == ReadDataBlockInfo->head.x && obj.head.y == ReadDataBlockInfo->head.y && obj.tail.x == ReadDataBlockInfo->tail.x && obj.tail.y == ReadDataBlockInfo->tail.y; });
if( s !=DataBlockHeadInfoList.end())
DataBlockHeadInfoList.erase(s);
return true;
}
bool ShareMemoryManager::GetCircularHeadSMI(int index)
{
if (index == CircularHeadSMI.CircularInfo.x)
{
return true;
}
else
{
CloseSharedMemory(CircularHeadSMI.sharedMemoryHandle);
if (-1 == OpenShareMemory(CircularHeadSMI, m_Main_DataSMNameList[index], m_Main_SMLength))
{
return false;
}
CircularHeadSMI.CircularInfo.x = index;
CircularHeadSMI.CircularInfo.y = 0;
return true;
}
}
DataBlock ShareMemoryManager::PushShareMemory(std::vector< unsigned __int8>& data)
{
DataBlock mDataBlock= WriteSharedMemory(&data[0], data.size());//write main data
mDataBlock.size = data.size();
DataBlockHeadInfoList.push_back(mDataBlock);
return mDataBlock;
}
DataBlock ShareMemoryManager::WriteSharedMemory(const unsigned char* data, int length)
{
if(!CheckRestSpace(length))
{
//how to waiting?
}
DataBlock mDataBlock;
if (m_Main_SMLength - 1 - CircularTailSMI.CircularInfo.y >= length)//1 //current sharememory have enough space
{
char* mWritePtr = (char*)CircularTailSMI.sharedMemoryHandle.m_MapView;
memcpy(mWritePtr + CircularTailSMI.CircularInfo.y + 1, data , length);
FlushViewOfFile(mWritePtr + CircularTailSMI.CircularInfo.y + 1, length);
mDataBlock.head.x = CircularTailSMI.CircularInfo.x;
mDataBlock.head.y = CircularTailSMI.CircularInfo.y + 1;
CircularTailSMI.CircularInfo.y += length;
mDataBlock.tail.x = CircularTailSMI.CircularInfo.x;
mDataBlock.tail.y = CircularTailSMI.CircularInfo.y;
return mDataBlock;
}
else// 2 not enough
{
//use current sharememory rest sapce
int length1 = m_Main_SMLength - 1 - CircularTailSMI.CircularInfo.y;
if (0 == length1)
{
mDataBlock.head.x = (CircularTailSMI.CircularInfo.x + 1) % nMaxBufferList;
mDataBlock.head.y = 0;
}
else
{
char* mWritePtr = (char*)CircularTailSMI.sharedMemoryHandle.m_MapView;
memcpy(mWritePtr + CircularTailSMI.CircularInfo.y + 1, data , length1);
FlushViewOfFile(mWritePtr + CircularTailSMI.CircularInfo.y + 1, length1);
mDataBlock.head.x = CircularTailSMI.CircularInfo.x;
mDataBlock.head.y = CircularTailSMI.CircularInfo.y + 1;
}
//use next sharememory space
int length2 = length - length1;
int count = length2/m_Main_SMLength + (length2%m_Main_SMLength > 0 ? 1 : 0);
for (int i = 0; i < count; i++)
{
if(GetNextCircularTailSMI())
{
int writeLength = (i == count -1) ? (length2 - m_Main_SMLength * i) : m_Main_SMLength;
char* mWritePtr = (char*)CircularTailSMI.sharedMemoryHandle.m_MapView;
memcpy(mWritePtr, data + length1 + m_Main_SMLength * i, writeLength);//begin from first
FlushViewOfFile(mWritePtr , writeLength);
CircularTailSMI.CircularInfo.y = writeLength - 1;
}
else
{
//open nex CircularTailSMI failed
}
}
mDataBlock.tail.x = CircularTailSMI.CircularInfo.x;
mDataBlock.tail.y = CircularTailSMI.CircularInfo.y;
return mDataBlock;
}
}
bool ShareMemoryManager::GetNextCircularTailSMI()
{
CloseSharedMemory(CircularTailSMI.sharedMemoryHandle);
if (-1 == OpenShareMemory(CircularTailSMI, m_Main_DataSMNameList[(CircularTailSMI.CircularInfo.x + 1) % nMaxBufferList], m_Main_SMLength))
{
return false;
}
CircularTailSMI.CircularInfo.x = (CircularTailSMI.CircularInfo.x + 1) % nMaxBufferList;
CircularTailSMI.CircularInfo.y = 0;
return true;
}
bool ShareMemoryManager::CheckRestSpace(int length)
{
HugeNumber restLength = GetCircularLength();
HugeNumber needLength;
needLength.x = 0;
needLength.y = length;
if (restLength.x > needLength.x)
{
return true;
}
else
{
return needLength.y < restLength.y;
}
}
HugeNumber ShareMemoryManager::GetCircularLength()
{
vector<DataBlock>::iterator iter = DataBlockHeadInfoList.begin();
HugeNumber restLength;
restLength.x = (CircularTailSMI.CircularInfo.x - iter->head.x + nMaxBufferList) %nMaxBufferList;
restLength.y = CircularTailSMI.CircularInfo.y - iter->head.y;
if (0 > restLength.y)
{
--restLength.x;
restLength.y = m_Main_SMLength + restLength.y;
}
return restLength;
}