32位进程如何使用大于2G的共享内存

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/gao271003105/article/details/85257422