自己备忘使用
//在共享内存中一定要做好挥斥信号量的使用,防止多个进程同时进行修改内存,可以吧共享内存作为临界资源处理
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace CommonLib
{
public class SharedMemory
{
#region DellImport
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr intPtr, int Msg, int wParam, IntPtr IParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr CreateFileMapping(int hFile, IntPtr ipAtttribute, uint flProtect, uint dwMaxSize, uint dwMaxSizeLow, string ipName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr OpenFileMapping(int dwDesAccess, [MarshalAs(UnmanagedType.Bool)] bool blHeritHanndle, string IpName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesireAccess, uint dwFileOffSetHigh, uint dwFileOffSetLow, uint dwNumberOfbytesToMap);
[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 hanndle);
[DllImport("kernel32.dll", EntryPoint = "GetLastError")]
public static extern int GetLatError();
#endregion
#region Const
const int Error_Alerady_Exists = 183;
const int File_Map_Write = 0x0002;
const int File_Map_Read = 0x0004;
const int File_Map_All_Access = 0x0002 | 0x0004;
const int Page_Read_Write = 0x04;
const int Invalib_Handle_value = -1;
const int Memory_MaxSize = 0x00800000;
#endregion
#region Var
IntPtr m_hSharedMemoryFile = IntPtr.Zero;
IntPtr m_pwData = IntPtr.Zero;
bool m_Blint = false;
long m_Memsize = 0;
Mutex mutex;
private string sharedMemoryName = string.Empty;
public string SharedMemoryName { get { return sharedMemoryName; } }
public long SharedMemorySize { get { return m_Memsize; } }
public enum InitResult
{
OK,
Fail,
ParamError,
}
#endregion
#region ctor
public SharedMemory(string moryName)
{
sharedMemoryName = moryName;
if (mutex == null)
{
var tempMut = CreateMutexOrOpen(moryName);
if (tempMut == null)
{
throw new Exception("Mutex is null");
}
else
{
mutex = tempMut;
}
}
}
///
/// 根据名称创建一个互斥资源
///
/// 互斥资源名称
///
private Mutex CreateMutexOrOpen(string moryName)
{
string mutName = moryName + "_Mutext";
Mutex tex = null;
try
{
tex = Mutex.OpenExisting(mutName);
}
catch { }
if (tex is null)
{
tex = new Mutex(false, mutName, out bool retBool);
}
return tex;
}
//析构函数在释放资源时候 调用
~SharedMemory()
{
Close();
}
#endregion
public InitResult Init(long memorySize)
{
mutex.WaitOne();
try
{
if (m_Blint)
{
return InitResult.OK;
}
if (string.IsNullOrEmpty(sharedMemoryName))
{
return InitResult.ParamError;
}
if (memorySize <= 0 || memorySize > Memory_MaxSize)
{
memorySize = Memory_MaxSize;
}
m_Memsize = memorySize;
//1. 创建内存共享体,存进字段
m_hSharedMemoryFile = CreateFileMapping(Invalib_Handle_value, IntPtr.Zero, (uint)Page_Read_Write, 0, (uint)memorySize, sharedMemoryName);
//2. 判断创建内存共享体是否成功
if (m_hSharedMemoryFile == IntPtr.Zero)
{
m_Blint = false;
return InitResult.Fail;
}
else
{
if (GetLatError() == Error_Alerady_Exists) //判断内存映射是否已经创建
{
m_Blint = true;
}
}
//3. 创建内存映射
m_pwData = MapViewOfFile(m_hSharedMemoryFile, File_Map_Write, 0, 0, (uint)memorySize);
//4. 判断内存映射是否成功
if (m_pwData == IntPtr.Zero)
{
m_Blint = false;
CloseHandle(m_hSharedMemoryFile);
return InitResult.Fail;
}
else
{
m_Blint = true;
return InitResult.OK;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
mutex.ReleaseMutex();
}
}
public void Close()
{
mutex.WaitOne();
if (m_Blint)
{
UnmapViewOfFile(m_pwData);
CloseHandle(m_hSharedMemoryFile);
}
mutex.ReleaseMutex();
mutex.Close();
}
public bool Read(ref byte[] byteData, int lngAddr, int lngSize)
{
if (lngAddr + lngSize > m_Memsize | m_pwData == IntPtr.Zero)
{
return false;
}
if (m_Blint)
{
mutex.WaitOne();
Marshal.Copy(m_pwData, byteData, lngAddr, lngSize);
mutex.ReleaseMutex();
}
else
{
return false;
}
return true;
}
///
/// 写入共享内存
///
/// 待写入的数据
/// 待写入数组的位置
/// 待写入数据长度
/// 偏移位置
///
public bool Write(byte[] byteData, int lngAddr, int lngSize, int Offset)
{
if (lngAddr + lngSize > m_Memsize)
{
return false;
}
if (m_Blint)
{
mutex.WaitOne();
Marshal.Copy(byteData, lngAddr, (IntPtr)(m_pwData.ToInt32() + Offset), lngSize);
mutex.ReleaseMutex();
}
else
{
return false;
}
return true;
}
public bool Clear()
{
byte[] bts = new byte[m_Memsize];
return Write(bts, 0, bts.Length, 0);
}
}
}