知识大全 使用共享内存在进程之间传送数据

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

相关参考

知识大全 oracle的共享连接和专用连接方式之初探

在专用连接方式中每一个连接到数据库服务器的客户端请求服务器会和客户端之间建立起连接这个连接用于专门处理该客户端的所有请求直到用户主动断开连接或网络出现中断在连接处于空闲时后台进程PMON会每隔一段时间

知识大全 共享内存在Java中的实现和应用

共享内存在Java中的实现和应用  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  共享内存对应应用

在推动会计信息化工作发展的进程中,代理记账机构需要做好哪些工作?

会计改革与发展十四五规划题目:在推动会计信息化工作发展的进程中,代理记账机构需要做好哪些工作?A、探索会计数据价值商业模式更新B、探索打造以会计数据为核心的数据聚合平台C、积极探索会计资源共享服务理念

知识大全 java多线程中synchronized关键字的用法

  由于同一进程内的多个线程共享内存空间在Java中就是共享实例当多个线程试图同时修改某个实例的内容时就会造成冲突因此线程必须实现共享互斥使多线程同步  最简单的同步是将一个方法标记为synchron

知识大全 数据结构考研分类复习真题 第三章 栈和队列[10]

  .两个栈共享一片连续内存空间时为提高内存利用率减少溢出机会应把两个栈的栈底分别设在这片内存空间的两端(   )【上海海运学院一(分)】  即使对不含相同元素的同一输入

知识大全 如何察看Oracle进程消耗的内存

如何察看Oracle进程消耗的内存  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  经常有人问到如

在开放数据网络中,信息在各层中是怎样进行传送的?

  信息传送的单位有“位”、“帧”、“信息包”、“报文”以及“用户数据”等;采用何种单位取决于具体的层次。  信息在各层中的传送如图6—13所示:  图6—13用户数据在各层中的传送形式和数据

在开放数据网络中,信息在各层中是怎样进行传送的?

  信息传送的单位有“位”、“帧”、“信息包”、“报文”以及“用户数据”等;采用何种单位取决于具体的层次。  信息在各层中的传送如图6—13所示:  图6—13用户数据在各层中的传送形式和数据

知识大全 oracle内存调优参数详解

  实例结构  oracle实例=内存结构+进程结构  oracle实例启动的过程其实就是oracle内存参数设置的值加载到内存中并启动相应的后台进程进行相关的服务过程  进程结构  oracle进程

知识大全 Oracle9i进程内存占用问题解决方法

Oracle9i进程内存占用问题解决方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  年月日发