2个进程(应用程序)之间的共享内存

Posted

技术标签:

【中文标题】2个进程(应用程序)之间的共享内存【英文标题】:Shared memory between 2 processes (applications) 【发布时间】:2011-01-01 13:33:57 【问题描述】:

我找不到这个问题的任何有用答案,尽管已经多次以不同的方式提出过这个问题。

我想在两个进程(两个不同的应用程序)之间共享内存, 这样其中一个可以写入该内存,另一个可以读取。

这在 .NET 中可行吗?怎么样?

谢谢

【问题讨论】:

复制:***.com/questions/439787/… 但是那个重复的问题也没有好的答案 重复问题中有很好的答案。你只是不喜欢他们说的话。但是 .NET 中没有内置方式来共享内存,您可以使用 P-Invoke 或尝试其他 IPC。 这正是我想听到的,我当时认为这在 .NET 中是不可能的(检查我的问题)我只需要有人来确认这一点。感谢您和 nobugz 以及所有其他人。 【参考方案1】:

目前,.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。并使用 unsafe 关键字,以便您可以创建指针。您需要为共享内存元素使用值类型(如结构)或使用 Marshal 类。

【讨论】:

您假设“共享数据”必须意味着直接共享托管对象。如果有人想分享一些“普通”数据怎么办? 不确定“普通”是什么意思。但是您仍然不能直接影响值类型的地址,它们存在于堆栈或 GC 堆中。需要一个指针才能将它们写入 MMF。 我认为普通数据,他的意思只是一堆你自己破译的字节,他只是想自己写代码来读/写内存映射文件 您能否评论一下这个答案的最新情况?有改进吗? 它仍然是最新的。【参考方案2】:

IPC

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

.Net 还提供了一些更高级别的 IPC,例如 .Net remoting 和 WCF,它们使用了前面提到的技术。你可以阅读更多关于它的信息here。

内存映射文件

如果您真的想共享一块内存而不是通信,那么也许内存映射文件就是您想要的。 .Net 4.0 有 MemoryMappedFile 。如果您不使用或不能使用 .Net 4.0,您可以像 win32 example 中那样自己实现它。或者你可以试试this 代码或者看看你是否可以使用提到here 和here 的MemoryMappedFileStream。或者使用这个FileMap 类。

【讨论】:

我不想使用命名管道、WCF、远程处理......等等......这就是为什么我指定“共享内存”,2个应用程序之间的共享内存很容易在c++中建立,但我无法在 C#.net 中找到一种方法,我正在使用 .NET 2.0,有没有办法使用它来解决这个问题?我不想参加第三次聚会【参考方案3】:

使用named pipe。

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

请注意,命名管道仅允许顺序读取。如果您需要使用更详细的查询,您可能需要使用客户端-服务器架构。在这种情况下,读取器进程使用network sockets 向其他进程查询信息。

【讨论】:

我不想使用命名管道、WCF、远程处理......等等......这就是为什么我指定“共享内存”,2个应用程序之间的共享内存很容易在c++中建立,但我无法在 C#.net 中找到方法 我还没有看到共享内存的任何直接实现,但是您可以轻松实现第三个进程,该进程将使用套接字处理两个进程的读写。 我认为每个人都没有抓住重点。共享内存与通过 any 机制同步对象有着根本的不同。使用共享内存,进程之间共享一致的状态。对于管道/wcf/etc,有一个(反)序列化/传输过程,这在周期方面是昂贵的。当您希望一个进程直接操作另一个进程中的对象时,使用共享内存(例如 Chrome 如何让多个进程渲染到同一个窗口中。直接绘制比一遍又一遍地序列化位图便宜得多)【参考方案4】:

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

【讨论】:

【参考方案5】:

这是一个实现,加上http://www.softwareinteractions.com/blog/2010/1/21/interprocess-communications-using-shared-memory.html的描述

【讨论】:

以上是关于2个进程(应用程序)之间的共享内存的主要内容,如果未能解决你的问题,请参考以下文章

Delphi XE2:在两个不同的进程之间共享一个变量?

通过使用 mmap() 在进程之间共享内存

Linux 进程详解

Gunicorn 在多处理进程和工作进程之间共享内存

如何在多个进程之间共享缓存?

Windows 进程和 WSL Linux 进程之间的共享内存