知识大全 使用共享内存在进程之间传送数据
Posted 知
篇首语:不畏过往,不惧将来。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 使用共享内存在进程之间传送数据相关的知识,希望对你有一定的参考价值。
今日在项目中碰到一个问题 就是一个程序的两个进程之间需要频繁的传送数据 具体的来说是一个需要频繁的发送数据而另一个实例需要频繁的访问获得这些数据 当然 这个问题是有很多解的 例如 数据库 再例如 文件 可是因为这个频繁程度太高了 例如 一秒钟十次 在这种情况下 使用数据库或者是文件可能都不是一个Good Idea
Update: 其实开始想到的方案还包括Remoting Socket之类的 不过明显的是小题大做 杀鸡用牛刀了 呵呵 所以最后也就放弃了
那么什么解决方案好呢?众所周知 内存的速度是除了CPU缓存外最快的 当然是我们的首选了 可是看遍了 Net的类库也没有找到可以用来实现这个方案的办法 看来只能依靠Win API了 在网上得到资料 可以使用API开辟共享内存从而达到在不同的进程之间共享数据的可能
关键API类
view sourceprint?public static class API
[DllImport( user dll CharSet = CharSet Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd int Msg int wParam IntPtr lParam);
[DllImport( Kernel dll CharSet = CharSet Auto)]
public static extern IntPtr CreateFileMapping(int hFile IntPtr lpAttributes uint flProtect uint dwMaxSizeHi uint dwMaxSizeLow string lpName);
[DllImport( Kernel dll CharSet = CharSet Auto)]
public static extern IntPtr OpenFileMapping(int dwDesiredAccess [MarshalAs(UnmanagedType Bool)] bool bInheritHandle string lpName);
[DllImport( Kernel dll CharSet = CharSet Auto)]
public static extern IntPtr MapViewOfFile(IntPtr hFileMapping uint dwDesiredAccess uint dwFileOffsetHigh uint dwFileOffsetLow uint dwNumberOfBytesToMap);
[DllImport( Kernel dll CharSet = CharSet Auto)]
public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);
[DllImport( Kernel dll CharSet = CharSet Auto)]
public static extern bool CloseHandle(IntPtr handle);
[DllImport( kernel EntryPoint = GetLastError )]
public static extern int GetLastError();
[DllImport( msvcrt dll SetLastError = true)]
public static extern int memcmp(IntPtr ptr IntPtr ptr int count);
[DllImport( msvcrt dll SetLastError = true)]
public static extern unsafe int memcmp(void* ptr void* ptr int count);
[DllImport( ntdll dll )]
public static extern int RtlCompareMemory(IntPtr Destination IntPtr Source int Length);
public const int ERROR_ALREADY_EXISTS = ;
public const int FILE_MAP_COPY = x ;
public const int FILE_MAP_WRITE = x ;
public const int FILE_MAP_READ = x ;
public const int FILE_MAP_ALL_ACCESS = x | x ;
public const int PAGE_READONLY = x ;
public const int PAGE_READWRITE = x ;
public const int PAGE_WRITECOPY = x ;
public const int PAGE_EXECUTE = x ;
public const int PAGE_EXECUTE_READ = x ;
public const int PAGE_EXECUTE_READWRITE = x ;
public const int SEC_MIT = x ;
public const int SEC_IMAGE = x ;
public const int SEC_NOCACHE = x ;
public const int SEC_RESERVE = x ;
public const int INVALID_HANDLE_VALUE = ;
代码实现
view sourceprint?public enum MemoryResult
Success
NotInitialized
NoChange
Failed
public class ShareMemory<T> : IDisposable
where T : class
IntPtr m_hSharedMemoryFile = IntPtr Zero;
IntPtr m_pwData = IntPtr Zero;
bool m_bAlreadyExist = false;
bool m_bInit = false;
long m_MemSize = ;
int m_size;
byte[] m_lastData;
public ShareMemory()
~ShareMemory()
Close();
/// <summary>
/// 初始化共享内存
/// </summary>
public MemoryResult Init(string strName)
m_size = ; //固定 K
var lngSize = m_size;
if (lngSize <= || lngSize > x ) lngSize = x ;
m_MemSize = lngSize;
if (strName Length > )
//创建内存共享体 (INVALID_HANDLE_VALUE)
m_hSharedMemoryFile = API CreateFileMapping(API INVALID_HANDLE_VALUE IntPtr Zero (uint)API PAGE_READWRITE (uint)lngSize strName);
if (m_hSharedMemoryFile == IntPtr Zero)
m_bAlreadyExist = false;
m_bInit = false;
return MemoryResult Failed; //创建共享体失败
else
if (API GetLastError() == API ERROR_ALREADY_EXISTS) //已经创建
m_bAlreadyExist = true;
else //新创建
m_bAlreadyExist = false;
//
//创建内存映射
m_pwData = API MapViewOfFile(m_hSharedMemoryFile API FILE_MAP_WRITE (uint)lngSize);
if (m_pwData == IntPtr Zero)
m_bInit = false;
API CloseHandle(m_hSharedMemoryFile);
return MemoryResult Failed; //创建内存映射失败
else
m_bInit = true;
if (m_bAlreadyExist == false)
//初始化
//
else
return MemoryResult Failed; //参数错误
return MemoryResult Success; //创建成功
/// <summary>
/// 关闭共享内存
/// </summary>
public void Close()
if (m_bInit)
API UnmapViewOfFile(m_pwData);
API CloseHandle(m_hSharedMemoryFile);
/// <summary>
/// 读数据
/// </summary>
public unsafe MemoryResult Read(out T obj)
obj = default(T);
byte[] bytData = new byte[m_size];
if (m_bInit)
Marshal Copy(m_pwData bytData m_size);
if (m_lastData != null)
fixed (byte* p = m_lastData)
fixed (byte* p = bytData)
if (mcmp(p p m_size) == )
return MemoryResult NoChange;
m_lastData = bytData;
var fmt = new BinaryFormatter();
using (var ms = new MemoryStream(bytData))
try
obj = (T)fmt Deserialize(ms);
catch (SerializationException)
return MemoryResult Failed;
else
return MemoryResult NotInitialized; //共享内存未初始化
return MemoryResult Success; //读成功
/// <summary>
/// 写数据
/// </summary>
public MemoryResult Write(T obj)
var fmt = new BinaryFormatter();
byte[] bytData;
if (obj is byte[])
bytData = obj as byte[];
else
using (var ms = new MemoryStream())
fmt Serialize(ms obj);
bytData = ms ToArray();
if (m_bInit)
Marshal Copy(bytData m_pwData bytData Length);
else
return MemoryResult NotInitialized; //共享内存未初始化
return MemoryResult Success; //写成功
#region IDisposable Members
public void Dispose()
Close();
#endregion
使用也很简单
view sourceprint?写数据
if (mem == null)
mem = new ShareMemory<ChannelStatus[]>();
mem Init( ChannelStatus );
var xml = PhoneCallHelper SendRequest(PhoneCallAction getChStatus);
foreach (XmlElement ele in xml DocumentElement SelectNodes( chStatus ))
var status = GetChannelStatusFromXElement(ele);
_status[status Channel] = status;
mem Write(_status Values ToArray());
读数据
using (var mem = new ShareMemory<ChannelStatus[]>())
if (mem Init( ChannelStatus ) != MemoryResult Success)
throw new Exception( 内存初始化失败 );
ChannelStatus[] status;
if (mem Read(out status) == MemoryResult Success)
return status;
return null;
cha138/Article/program/net/201311/13598相关参考