c#读写共享内存操作函数封装

原文 c#读写共享内存操作函数封装

  c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂。

        现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方面则是做个备份吧。

 

[csharp] view plaincopy

  1. /// <summary>  
  2.         /// 写共享内存  
  3.         /// </summary>  
  4.         /// <param name="structSize">需要映射的文件的字节数量</param>  
  5.         /// <param name="obj">映射对象(简单类型、结构体等)</param>  
  6.         /// <param name="fileName">文件映射对象的名称</param>  
  7.         /// <param name="windowName">发送消息的窗口句柄</param>  
  8.         /// <param name="Msg">发送消息</param>  
  9.         /// <returns></returns>  
  10.         public static int WriteToMemory(uint structSize, Object obj, string fileName, string windowName, uint Msg)  
  11.         {  
  12.             IntPtr hShareMemoryHandle = IntPtr.Zero;  
  13.             IntPtr hVoid = IntPtr.Zero;  
  14.   
  15.             //判断参数的合法性  
  16.             if (structSize > 0 && fileName.Length > 0)  
  17.             {  
  18.                 hShareMemoryHandle = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)structSize, fileName);  
  19.                 if (hShareMemoryHandle == IntPtr.Zero)  
  20.                 {  
  21.                     //创建共享内存失败,记log  
  22.                     MessageBox.Show("创建共享内存失败"+publicInfo.GetLastError().ToString());  
  23.                     return -2;  
  24.                 }  
  25.                 else  
  26.                 {  
  27.                     if (ERROR_ALREADY_EXISTS == GetLastError())  
  28.                     {  
  29.                         //共享内存已经存在,记log  
  30.                         MessageBox.Show("共享内存已经存在");  
  31.                         return -3;  
  32.                     }  
  33.                 }  
  34.                 hVoid = MapViewOfFile(hShareMemoryHandle, FILE_MAP_WRITE, 0, 0, structSize);  
  35.                 if (hVoid == IntPtr.Zero)  
  36.                 {  
  37.                     CloseHandle(hShareMemoryHandle);  
  38.                     //文件映射失败,记log  
  39.                     MessageBox.Show("文件映射失败");  
  40.                     return -4;  
  41.                 }  
  42.                 Marshal.StructureToPtr(obj, hVoid, false);  
  43.                 //发送消息,通知接收  
  44.                 IntPtr handle = FindWindow(null, windowName.Trim());  
  45.                 if (handle == IntPtr.Zero)  
  46.                 {  
  47.                     //查找窗口失败,记log  
  48.                     MessageBox.Show("查找窗口失败");  
  49.                     return -5;  
  50.                 }  
  51.                 else  
  52.                 {  
  53.                     if (PostMessage(handle, (uint)Msg, 0, 0))  
  54.                     {  
  55.                         //发送消息成功  
  56.                         //MessageBox.Show("写共享内存,通知发送消息成功");  
  57.                     }  
  58.                 }  
  59.             }  
  60.             else  
  61.             {  
  62.                 //参数不合法,记log  
  63.                 MessageBox.Show("共享内存已经存在");  
  64.                 return -1;  
  65.             }  
  66.             return 0;  
  67.         }  

  写共享内存函数并没有什么需要说明,完全按照:

 

创建共享内存文件(CreateFileMapping)---》映射文件视图到调用进程的地址空间(MapViewOfFile)---》写数据到共享内存(Marshal.StructureToPtr)----》发送消息通知需要读共享内存的窗口(PostMessage)

 

[csharp] view plaincopy

  1. /// <summary>  
  2.         /// 读共享内存  
  3.         /// </summary>  
  4.         /// <param name="structSize">需要映射的文件的字节数量</param>  
  5.         /// <param name="type">类型</param>  
  6.         /// <param name="fileName">文件映射对象的名称</param>  
  7.         /// <returns>返回读到的映射对象</returns>  
  8.         public static Object ReadFromMemory(uint structSize, Type type, string fileName)  
  9.         {  
  10.   
  11.             IntPtr hMappingHandle = IntPtr.Zero;  
  12.             IntPtr hVoid = IntPtr.Zero;  
  13.   
  14.             hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);  
  15.             if (hMappingHandle == IntPtr.Zero)  
  16.             {  
  17.                 //打开共享内存失败,记log  
  18.                 MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());  
  19.                 return null;  
  20.             }  
  21.             hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);  
  22.             if (hVoid == IntPtr.Zero)  
  23.             {  
  24.                 //文件映射失败,记log  
  25.                 MessageBox.Show("文件映射失败——读共享内存");  
  26.                 return null;  
  27.             }  
  28.   
  29.             Object obj = Marshal.PtrToStructure(hVoid, type);  
  30.   
  31.             if (hVoid != IntPtr.Zero)  
  32.             {  
  33.                 UnmapViewOfFile(hVoid);  
  34.                 hVoid = IntPtr.Zero;  
  35.             }  
  36.             if (hMappingHandle != IntPtr.Zero)  
  37.             {  
  38.                 CloseHandle(hMappingHandle);  
  39.                 hMappingHandle = IntPtr.Zero;  
  40.             }  
  41.             return obj;  
  42.         }  

 

         读共享内存,上边代码是一种方式,这里是传入一个Type类型,这样就确保可以传入任何类型。当读到共享内存的数据时,采用

         public static object PtrToStructure(IntPtr ptr, Type structureType);

        函数,把非托管指针(共享内存获得的指针)转换为需要转换的Type类型的对象。如果需要的话,可以通过显示类型转换转换为需要的类型(例子继续看)。

       

[csharp] view plaincopy

  1. /// <summary>  
  2.         /// 读共享内存  
  3.         /// </summary>  
  4.         /// <param name="structSize">需要映射的文件的字节数量</param>  
  5.         /// <param name="type">类型</param>  
  6.         /// <param name="fileName">文件映射对象的名称</param>  
  7.         /// <returns>返回读到的映射字节数据</returns>  
  8.         public static byte[] ReadFromMemory(uint structSize, Type type, string fileName)  
  9.         {  
  10.   
  11.             IntPtr hMappingHandle = IntPtr.Zero;  
  12.             IntPtr hVoid = IntPtr.Zero;  
  13.   
  14.             hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);  
  15.             if (hMappingHandle == IntPtr.Zero)  
  16.             {  
  17.                 //打开共享内存失败,记log  
  18.                 MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());  
  19.                 return null;  
  20.             }  
  21.             hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);  
  22.             if (hVoid == IntPtr.Zero)  
  23.             {  
  24.                 //文件映射失败,记log  
  25.                 MessageBox.Show("文件映射失败——读共享内存");  
  26.                 return null;  
  27.             }  
  28.   
  29.             //Object obj = Marshal.PtrToStructure(hVoid, type);  
  30.             byte[] bytes = new byte[structSize];  
  31.             Marshal.Copy(hVoid, bytes, 0, bytes.Length);  
  32.   
  33.             if (hVoid != IntPtr.Zero)  
  34.             {  
  35.                 UnmapViewOfFile(hVoid);  
  36.                 hVoid = IntPtr.Zero;  
  37.             }  
  38.             if (hMappingHandle != IntPtr.Zero)  
  39.             {  
  40.                 CloseHandle(hMappingHandle);  
  41.                 hMappingHandle = IntPtr.Zero;  
  42.             }  
  43.             return bytes;  
  44.         }  

        此代码和第一个读共享内存不同的是,采用byte[]读需要的共享内存。使用托管类中的Copy来转换指针。

 

 

[csharp] view plaincopy

  1. byte[] bytes = new byte[structSize];  
  2. arshal.Copy(hVoid, bytes, 0, bytes.Length);  

 

      调用简单例子部分代码如下:

注:passiveInfo是NotifyInfo结构体对象。

      写共享内存:

 

[csharp] view plaincopy

  1. int iRet = publicInfo.WriteToMemory((uint)Marshal.SizeOf(passiveInfo),(Object)passiveInfo, "memName","FormMsg",(uint)publicInfo.WM_NOTIFY);  

 

     读共享内存:

第一种情况调用:

 

[csharp] view plaincopy

  1. passiveInfo = (NotifyPassiveInfo)publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), typeof(NotifyPassiveInfo), publicInfo.SN_PASSIVEINFO);  

      第二种情况调用:

 

[csharp] view plaincopy

  1. byte[] bytes = publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), "memName");  
  2. passiveInfo = (NotifyInfo)BytesToStuct(bytes, typeof(NotifyInfo));  

 

 

      希望对你有帮助。

     转载请标注:http://blog.csdn.net/richerg85

时间: 2024-09-28 04:46:48

c#读写共享内存操作函数封装的相关文章

共享内存操作类(C#源码)

  原文 http://blog.csdn.net/yefanqiu/article/details/1717458   VC++的共享内存操作代码实现起来相对比较容易,但是用C#语言来实现,就有一定难度,由于工作需要,把以前VC开发的共享内存代码要用C#实现,别说,还费了不少周折,毕竟C#操作API函数和地址指针不是那么直接,还好,总算完成了,效果还不错.      共享内存操作类:     using System;using System.Collections.Generic;using

android 匿名共享内存ashmem_create_region函数有没有对应的释放函数

问题描述 android 匿名共享内存ashmem_create_region函数有没有对应的释放函数 RT,ashmem_create_region 函数对应的release函数?且不释放会不会影响系统性能? 解决方案 ashmem_create_region返回的是一个文件句柄fd,所以关闭就采用文件关闭函数close就好了. 解决方案二: ashmem_unpin_region(fd, 0, 0);

js 读写删除cookies操作函数

js 读写删除cookies操作函数 function setcookie(name,value)//两个参数,一个是cookie的名子,一个是值 {     var days = 30; //此 cookie 将被保存 30 天     var exp  = new date();    //new date("december 31, 9998");     exp.settime(exp.gettime() + days*24*60*60*1000);     document.

PCI设备内存操作函数总结

1.  ExAllocatePool() 函数说明: ExAllocatePool allocates pool memory of the specified type and returns a pointer to the allocated block. 函数定义: PVOID ExAllocatePool(                             __in  POOL_TYPE PoolType,                             __in  SI

共享内存

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]:一次从输入

ipcs ipcrm 信号量(命令)+ 共享内存函数shmget、shmat、shmdt、shmctl

 unix/linux下的共享内存.信号量.队列信息管理,在unix/linux下,经常有因为共享内存.信号量,队列等共享信息没有干净地清楚而引起一些问题. 1.ipcs 和 ipcrm 命令实例 查看共享信息的内存的命令是ipcs [-m|-s|-q]. 默认会列出共享内存.信号量,队列信息,-m列出共享内存,-s列出共享信号量,-q列出共享队列 清除命令是ipcrm [-m|-s|-q] id. ipcrm可用来删除对应的共享内存段.信号量.消息队列:ipcrm本身只能实现单个资源的删除,利

进程间通信之-共享内存Shared Memory--linux内核剖析(十一)

共享内存 共享内存是进程间通信中最简单的方式之一. 共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区. 共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改. 关于共享内存 当一个程序加载进内存后,它就被分成叫作页的块. 通信将存在内存的两个页之间或者两个独立的进程之间. 总之,当一个程序想和另外一个程序通信的时候,那内存将会为这两个程序生成一块公共的

win32下进程间通信(共享内存)实例分析_C 语言

一.概述 很多情况下在Windows程序中,各个进程之间往往需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换. 进程间通讯(即:同机通讯)和数据交换有多种方式:消息.共享内存.匿名(命名)管道.邮槽.Windows套接字等多种技术."共享内存"(shared memory)可以定义为对一个以上的进程是可见的内存或存在于多个进程的虚拟地址空间.例如:如果两个进程使用相同的DLL,只把DLL的代码

单台服务器的PHP进程之间实现共享内存的方法_php技巧

开发人员要想使php进程实现共享内存的读写,首先就要支持IPC函数,即php编译安装时指定:--enable-shmop  与--enable-sysvsem 两个选项. IPC (Inter-process communication) 是一个Unix标准机制,它提供了使得在同一台主机不同进程之间可以互相的方法.基本的IPC处理机制有3种:它们分别是共享内存.信号量和消息队列.本文中我们主要讨论共享内存和信号量的使用. 在不同的处理进程之间使用共享内存是一个实现不同进程之间相互的好方法.如果你