【第22期】观点:IT 行业加班,到底有没有价值?

C#下的进程间的通讯 -- 共享内存--内存互斥控制

转载 2011年01月11日 17:36:00

  C#下的进程间的通讯 -- 共享内存篇 收藏
 【摘要】
这篇文章早就想发了,可是一直没有时间整理,今天总算发上来了。

上次发了利用发消息实现的C#进程间的通讯,这次又使用共享内存了,他们应用范围是不同的,共享内存适用于共享大量数据的情况。
本文章利用了前面的一篇.net 1.1 下实现的信号量的类,在.net 1.1 下实现,如果在.net 2.0 下实现的话就用不到我的那个信号量的类了,因为这个类在.net 2.0是提供的。

【全文】

首先还是定义非托管调用,如下:


const int INVALID_HANDLE_VALUE = -1;
const int PAGE_READWRITE = 0x04;
  //共享内存
  [DllImport("Kernel32.dll",EntryPoint="CreateFileMapping")]
  private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,
   UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //0
   UInt32 flProtect,//DWORD flProtect
   UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh,
   UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow,
   string lpName//LPCTSTR lpName
   );
  [DllImport("Kernel32.dll",EntryPoint="OpenFileMapping")]
  private static extern IntPtr OpenFileMapping(
   UInt32 dwDesiredAccess,//DWORD dwDesiredAccess,
   int bInheritHandle,//BOOL bInheritHandle,
   string lpName//LPCTSTR lpName
   );
  const int FILE_MAP_ALL_ACCESS = 0x0002;
  const int FILE_MAP_WRITE = 0x0002;
  [DllImport("Kernel32.dll",EntryPoint="MapViewOfFile")]
  private static extern IntPtr MapViewOfFile(
   IntPtr hFileMappingObject,//HANDLE hFileMappingObject,
   UInt32 dwDesiredAccess,//DWORD dwDesiredAccess
   UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh,
   UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow,
   UInt32 dwNumberOfBytesToMap//SIZE_T dwNumberOfBytesToMap
   );
  [DllImport("Kernel32.dll",EntryPoint="UnmapViewOfFile")]
  private static extern int UnmapViewOfFile(IntPtr lpBaseAddress);
  [DllImport("Kernel32.dll",EntryPoint="CloseHandle")]
  private static extern int CloseHandle(IntPtr hObject);
然后分别在AB两个进程中定义如下两个信号量及相关变量;

  private Semaphore m_Write;  //可写的信号
  private Semaphore m_Read;  //可读的信号
  private IntPtr handle;     //文件句柄
  private IntPtr addr;       //共享内存地址
  uint mapLength;            //共享内存长

定义这两个信号量是为读写互斥用的。
在A进程中创建共享内存:

m_Write = new Semaphore(1,1,"WriteMap");
m_Read = new Semaphore(0,1,"ReadMap");
mapLength = 1024;
IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE);  
handle = CreateFileMapping(hFile,0,PAGE_READWRITE,0,mapLength,"shareMemory");
addr = MapViewOfFile(handle,FILE_MAP_ALL_ACCESS,0,0,0);
然后再向共享内存中写入数据:

m_Write.WaitOne();
byte[] sendStr = Encoding.Default.GetBytes(txtMsg.Text + '/0');
//如果要是超长的话,应另外处理,最好是分配足够的内存
if(sendStr.Length < mapLength)
      Copy(sendStr,addr);
m_Read.Release();

这是在一个单独的方法中实现的,可多次调用,但受信号量的控制。其中txtMsg是一个文本框控件,实际中可用任意字符串,加最后的'/0'是为了让在共享内存中的字符串有一个结束符,否则在内存中取出时是以'/0'为准的,就会出现取多的情况。
Copy方法的实现如下:

static unsafe void Copy(byte[] byteSrc,IntPtr dst)
  {
   fixed (byte* pSrc = byteSrc)
   {
    byte* pDst = (byte*)dst;
    byte* psrc = pSrc;
    for(int i=0;i<byteSrc.Length;i++)
    {
     *pDst = *psrc;
     pDst++;
     psrc ++;
    }
   }
  }
注意unsafe 关键字,在编译时一定要打开非安全代码开关。
最后不要忘了在A进程中关闭共享内存对象,以免内存泄露。

   UnmapViewOfFile(addr);
   CloseHandle(handle);

要在B进程中读取共享内存中的数据,首先要打开共享内存对象:

m_Write = Semaphore.OpenExisting("WriteMap");
m_Read = Semaphore.OpenExisting("ReadMap");
handle = OpenFileMapping(0x0002,0,"shareMemory");
读取共享内存中的数据:

   m_Read.WaitOne();
   string str = MapViewOfFile(handle,FILE_MAP_ALL_ACCESS,0,0,0);
   txtMsg.Text = str;
   m_Write.Release();
这里获取了字符串,如果要获取byte数组,请参考上面的Copy函数实现。
=================================================================================================
来源:http://www.x2blog.cn/jinhong618/21581.html


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/dhz123/archive/2008/07/25/2708883.aspx

举报

相关文章推荐

共享内存实现进程间大数据的交换

http://www.x2blog.cn/jinhong618/21581.html相关下载:http://www.x2blog.cn/jinhong618/UserFiles/ProcessComm...

多线程服务器的常用编程模型

多线程服务器的常用编程模型 陈硕(giantchen_AT_gmail) Blog.csdn.net/Solstice <p class="

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

C#下的进程间的通讯 -- 共享内存篇

【摘要】这篇文章早就想发了,可是一直没有时间整理,今天总算发上来了。上次发了利用发消息实现的C#进程间的通讯,这次又使用共享内存了,他们应用范围是不同的,共享内存适用于共享大量数据的情况。本文章利用了...
  • dhz123
  • dhz123
  • 2008-07-25 11:11
  • 1961

C++多线程程序设计经验

转自:http://blog.csdn.net/Solstice/article/details/5307710 <p class="p21" style="color: #333333; font-family: Arial; font-size: 14px;...

C#进程间通讯技术-整理。

扩展阅读:http://www.cnblogs.com/joye-shen/archive/2012/06/16/2551864.html 一、进程间通讯的方式 1)共享内存 ...
  • wlanye
  • wlanye
  • 2013-01-29 13:12
  • 2695
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)