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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值