2010-01-05 157 views
16

虽然已经多次以不同方式询问了此问题,但我找不到任何有用的答案。2个进程(应用程序)之间的共享内存

我想两个进程(两个不同的应用程序)之间共享内存, 让他们中的一个可以写入到存储器和其它可以读取。

这是可能的.NET?怎么样?

谢谢

+0

重复:http://stackoverflow.com/questions/439787/how-to-implement-shared-memory-in-net – 2010-01-05 08:29:57

+0

但没有很好的答案在那个重复的问题中 – 2010-01-05 09:19:39

+0

在重复的问题中有很好的答案。你只是不喜欢他们说的话。但是在.NET中没有共享内存的方式,您可以使用P-Invoke或尝试其他IPC。 – Niki 2010-01-05 11:15:03

回答

29

现在,.NET不支持部分(又名内存映射文件)。很快,4.0版本将具有System.IO.MemoryMappedFiles名称空间。这是一个很好的理由花了这么长时间,也是你不会满意这个补充的原因。在MMF中使用指针是强制性的,共享内存在特定地址可用。要分享一个值,你必须把它写到一个特定的地址。

指针与托管内存模型基本上不兼容。对象在垃圾收集堆中创建,收集器根据需要移动它们以保持堆压缩。在托管语言中,你有这样一个对象的引用,也被称为“追踪句柄”。 C/C++等价物是一个指针,但它是一个带有铃声的指针,垃圾收集器总是可以找回它并更新它的值。 CLR确实支持“钉住”的概念,它将引用转换为指针。它通过将对象标记为不可移动来实现此目的。然而,这无助于通过MMF实现共享内存,该对象被固定在GC堆中,而不是MMF视图所在的虚拟内存地址。

要使MMF工作,需要将对象从GC堆复制到共享内存。这需要序列化。 .NET 4.0类被命名为MemoryMappedViewStream。您可能会看到这是怎么回事,这与使用命名管道或套接字无法区分。获取数据进出MMF需要付出相同的努力。由于基础缓冲区不在内核内存池中,所以MMF的效率稍微高一点。

你可以打破规则,并今天这样做。你可以P/Invoke你需要创建一个MMF的CreateFileMapping,OpenFileMapping和MapViewOfFile。并使用不安全的关键字,以便您可以创建指针。您需要为共享内存元素使用值类型(如struct)或使用Marshal类。

+2

您假定“共享数据”必须意味着直接共享管理对象。如果有人想分享一些“简单”的数据会怎么样? – devdimi 2010-01-05 12:27:33

+0

不确定“简单”是什么意思。但是,您仍然不能直接影响值类型的地址,它们将处于堆栈或GC堆中。需要一个指针才能将它们写入MMF。 – 2010-01-05 12:42:40

+1

我认为通过明文数据,他意味着只是你自己破译的一堆字节,他只是想写代码来自己读/写内存映射文件 – BlueTrin 2013-01-29 10:45:19

1

使用named pipe

这是一种机制,它允许一个进程将顺序数据写入流中,其他进程可以从中读取数据。

请注意,命名管道只允许顺序读取。如果您需要使用更详细的查询,则可能需要使用客户端 - 服务器体系结构。在这种情况下,读者进程使用network sockets向另一个进程查询信息。

+0

我不想使用命名管道,WCF,远程处理等......这就是为什么我指定“共享内存”,2个应用程序之间的共享内存很容易建立在C++中,但我无法找到一种方法在C#中执行.net – 2010-01-05 09:20:59

+0

我还没有看到共享内存的任何直接实现,但是您可以轻松实现第三个进程,该进程将使用套接字处理读取和写入这两个进程。 – 2010-01-05 10:03:01

+1

我想大家都错过了这一点。共享内存与通过_any_机制同步对象有着根本的区别。通过共享内存,进程之间可以共享一致的状态。使用pipes/wcf/etc,有一个(de)序列化/发送过程,在循环方面是昂贵的。共享内存用于当一个进程直接操纵另一个对象时(比如说,Chrome将多个进程渲染到同一个窗口中)直接绘制比串行化位图要便宜得多 – Basic 2014-08-15 00:31:13

4

IPC

如果你是在谈论进程间通信。有几种可能性,例如使用tcp/udp套接字,邮筒,命名管道,内存映射文件,windows消息等。

.net还提供一些更高级别的IPC,如.Net remotingWCF,它们使用前面提到的技术。你可以阅读更多关于它here

内存映射文件

如果你真的想分享的内存块,而不是通信的话,说不定内存映射文件是你想要什么。 .Net 4.0有MemoryMappedFile。如果你没有或不能使用.Net 4.0,你可以像这个win32 example一样自己实现它。或者您可以尝试this代码或查看是否可以使用MemoryMappedFileStream提到的herehere。或者使用这个FileMap类。

+0

我不想使用命名管道,WCF,远程处理...等...这就是为什么我指定“共享内存”,2个应用程序之间的共享内存很容易在C++中建立,但我无法找到一种方式在C#中完成.net 我使用.NET 2.0,有无论如何解决这个使用它?我不想扔第三方 – 2010-01-05 09:22:18

+0

更新了我的答案并提供了更多信息 – 2010-01-05 10:04:39

0

正如已经提到的使用内存映射文件。 NET的实现< 4 available at:http://github.com/tomasr/filemap/
我已经使用它,它的工作完美无瑕。在升级/未升级的进程之间共享时,您可能会遇到一些安全问题 - 解决方案是在升级的进程中初始化内存映射文件并相应地设置其安全属性。

相关问题