共享内存的应用(C++,C#)
定义
共享内存指 (shared memory)在多处理器的计算机系统中,可以被不同CPU访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后,共享内存需要立即更新。共享内存是 Unix下的多进程之间的通信方法,可用于同一程序中的多进程或多程序中。
示例
c#应用
SharedMemory.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShareMemoryCs
{
public class ShareMemory
{
public enum RETVAL
{
SUCCESS= 0,
FAILURE = -10000,
}
private System.IO.MemoryMappedFiles.MemoryMappedFile mmf;
private System.IO.MemoryMappedFiles.MemoryMappedViewAccessor viewAccessor;
public int MemorySize
{
get;
set;
}
public string MemoryName
{
set;
get;
}
public ShareMemory()
{
MemoryName = "test_share_memory";
MemorySize = 1 << 10 << 16;
}
public int Init(string strMemoryName)
{
if (String.IsNullOrEmpty(strMemoryName))
return RETVAL.FAILURE.GetHashCode();
MemoryName = strMemoryName;
mmf = System.IO.MemoryMappedFiles.MemoryMappedFile.CreateOrOpen(MemoryName, MemorySize, System.IO.MemoryMappedFiles.MemoryMappedFileAccess.ReadWrite);
viewAccessor = mmf.CreateViewAccessor(0, MemorySize);
return RETVAL.SUCCESS.GetHashCode();
}
public int InputData(string strTxt)
{
viewAccessor.Write(0, strTxt.Length);
viewAccessor.WriteArray<char>(0, strTxt.ToArray(), 0, strTxt.Length);
return RETVAL.SUCCESS.GetHashCode();
}
public int OutputData(out string strTxt)
{
//这里要指定Unicode编码否则会出问题
//读取字符
int length = viewAccessor.ReadInt32(0);
char[] charsInMMf = new char[length];
viewAccessor.ReadArray<char>(0, charsInMMf, 0, length);
strTxt = String.Join("", charsInMMf);
strTxt = strTxt.TrimEnd('\0');
return RETVAL.SUCCESS.GetHashCode();
}
public void ClearMemory()
{
char[] charsInMMf = new char[MemorySize];
viewAccessor.WriteArray<char>(0, charsInMMf, 0, MemorySize/2);
}
public void Dispose()
{
if(viewAccessor!=null)
viewAccessor.Dispose();
if (mmf != null)
mmf.Dispose();
}
}
}
c++应用
SharedMemory.h
#pragma once
#include
#include
#include
#include
#ifdef SHAREMEMORY_EXPORTS
#define SHAREMEMORY_DLL __declspec(dllexport)
#else
#define SHAREMEMORY_DLL __declspec(dllimport)
#endif
enum ErrorDefine
{
SUCCESS = 0,
FAILURE = -50000,
};
struct ShareMemoryParam
{
wchar_t strName[CHAR_MAX];
void* m_pBuffer;
void* m_hMap;
ShareMemoryParam()
{
memset(strName, 0, CHAR_MAX*sizeof(wchar_t));
m_pBuffer = NULL;
m_hMap = NULL;
}
};
class SHAREMEMORY_DLL CShareMemory
{
public:
CShareMemory();
~CShareMemory();
public:
int Init(std::wstring& strName);
int InputData(std::wstring& strTxt);
int OutputData(std::wstring& strTxt);
void ClearMemroy();
void Dispose();
void SetShareMemoryName(std::wstring& strName);
private:
std::wstring m_sShareMemoryName;
int m_MemorySize;
std::map<int, ShareMemoryParam> m_smp;
};
SharedMemory.cpp
// ShareMemory.cpp : 定义 DLL 应用程序的导出函数。
//
#include “stdafx.h”
#include “ShareMemory.h”
CShareMemory::CShareMemory() {
m_sShareMemoryName = L"test_share_memeory";
m_MemorySize = 1 << 10 << 16;
}
CShareMemory::~CShareMemory()
{
Dispose();
}
int CShareMemory::Init(std::wstring& strName)
{
if (!strName.empty())
m_sShareMemoryName = strName;
ShareMemoryParam _smp;
HANDLE hMap;
LPVOID pBuffer;
// 首先试图打开一个命名的内存映射文件对象
hMap = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, (LPCWSTR)m_sShareMemoryName.c_str());
if (NULL == hMap)
{
// 打开失败,创建之
hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, m_MemorySize, (LPCWSTR)m_sShareMemoryName.c_str());
// 打开成功,映射对象的一个视图,得到指向共享内存的指针
pBuffer = ::MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, m_MemorySize);
}
else
{
pBuffer = ::MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
}
memcpy(_smp.strName, m_sShareMemoryName.c_str(), m_sShareMemoryName.length()*sizeof(wchar_t));
_smp.m_hMap = hMap;
_smp.m_pBuffer = pBuffer;
m_smp.insert(std::pair<int, ShareMemoryParam>();
if (pBuffer)
return SUCCESS;
else
return FAILURE;
}
int CShareMemory::InputData(std::wstring& strTxt)
{
if (strTxt.length() * sizeof(wchar_t) > m_MemorySize)
return FAILURE;
//写数据
for (int i = 0; i < m_smp.size(); i++)
{
if (std::wstring(m_smp[i].strName) == m_sShareMemoryName)
memcpy(m_smp[i].m_pBuffer, strTxt.c_str(), (strTxt.length() + 1) * sizeof(wchar_t));
}
return SUCCESS;
}
int CShareMemory::OutputData(std::wstring& strTxt)
{
//写数据
for (int i = 0; i < m_smp.size(); i++)
{
if (std::wstring(m_smp[i].strName) == m_sShareMemoryName)
strTxt = std::wstring((wchar_t*)m_smp[i].m_pBuffer);
}
return SUCCESS;
}
void CShareMemory::ClearMemroy()
{
for (int i = 0; i < m_smp.size(); i++)
{
if (std::wstring(m_smp[i].strName)==m_sShareMemoryName)
{
memset(m_smp[i].m_pBuffer, 0, m_MemorySize);
break;
}
}
}
void CShareMemory::Dispose()
{
// 解除文件映射,关闭内存映射文件对象句柄
for (int i = 0; i < m_smp.size(); i++)
{
if (m_smp[i].m_pBuffer)
::UnmapViewOfFile(m_smp[i].m_pBuffer);
if (m_smp[i].m_hMap)
::CloseHandle(m_smp[i].m_hMap);
m_smp[i].m_pBuffer = NULL;
m_smp[i].m_hMap = NULL;
}
}
void CShareMemory::SetShareMemoryName(std::wstring& strName)
{
m_sShareMemoryName = strName;
}
总结
以上是基本的共享内存应用,通过设定共享内存名称,访问映射的内存中数据,在程序中或程序间均可自由快速访问。
后续待增加功能点:共享内存没有任何的同步与互斥机制,所以需要使用信号量来实现对共享内存的存取的同步。