虽然类似的问题已经被提出过几次,但是我并没有找到有用的答案。
我想在两个进程之间(即两个不同的应用程序)共享一个内存,以便其中一个进程可以向该内存写入数据,而另一个进程可以读取该内存。
.NET中是否可能实现这一功能?如何实现?
谢谢。
虽然类似的问题已经被提出过几次,但是我并没有找到有用的答案。
我想在两个进程之间(即两个不同的应用程序)共享一个内存,以便其中一个进程可以向该内存写入数据,而另一个进程可以读取该内存。
.NET中是否可能实现这一功能?如何实现?
谢谢。
目前,.NET框架不支持Memory Mapped Files (内存映射文件)。然而,在.NET 4.0版本中,将引入System.IO.MemoryMappedFiles命名空间来支持这一功能。这项更新花费了很长时间,但是它的实现方式可能会让您不太满意。在MMFs中使用指针是必需的,因为共享内存是在特定地址上可用的。要共享一个值,您必须将其写入到特定地址。
然而,指针与托管内存模型根本不兼容。对象创建在一个垃圾回收堆中,垃圾收集器会根据需要移动它们以保持堆的紧凑性。在托管语言中,您有一个对这种对象的引用,也称为“跟踪句柄”。C/C++的等价物是指针,但是它带有附加功能。垃圾回收器始终可以找到并更新其值。CLR支持“pinning”的概念,它将引用转换为指针。它通过标记对象为不可移动来实现。但是,这并不能帮助通过MMF实现共享内存,因为对象在GC堆中被固定,而不是在MMF视图所在的虚拟内存地址中。
要使MMF正常工作,需要将对象从GC堆复制到共享内存中。这需要序列化。在.NET 4.0中,相关类名为MemoryMappedViewStream。您可能已经看出来,这与使用命名管道或套接字没有区别。从MMF中获取数据和传递数据需要同样的努力。MMF仅仅是稍微更加高效,因为底层缓冲区不在内核内存池中。
您可以打破规则并立即这么做。您可以P/Invoke CreateFileMapping、OpenFileMapping和MapViewOfFile函数以创建MMF。并使用unsafe关键字以便创建指针。您需要使用值类型(如结构体)来表示共享内存元素,或者使用Marshal类。
IPC
如果你谈论的是进程间通信(IPC),那么有几种可能性,比如使用tcp/udp套接字、邮槽、命名管道、内存映射文件、Windows消息等。
.Net还提供了一些更高级的IPC,如.Net Remoting和WCF,它们使用了前面提到的技术。你可以在这里阅读更多相关信息。
Memory Mapped Files
如果你真的想共享一个内存块而不是进行通信,那么也许内存映射文件正是你所需要的。.Net 4.0有MemoryMappedFile为此提供支持。如果你不能或不想使用.Net 4.0,你可以像win32示例中的代码一样自己实现它。或者你可以尝试使用这个代码,或者看看是否可以使用在这里和这里提到的MemoryMappedFileStream。又或者使用这个FileMap类。