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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2004790/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:44:43  来源:igfitidea点击:

Shared memory between 2 processes (applications)

.netmemoryipcpipenamed-pipes

提问by Tea Bee

I can't find any useful answer for this question, although it has been asked in a different way several times.

我找不到这个问题的任何有用的答案,尽管它已经以不同的方式被问过好几次了。

I want to share a memory between two processes (two different applications), so that one of them can write to that memory and the other can read.

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

Is this possible in .NET? How?

这在 .NET 中可能吗?如何?

Thanks

谢谢

回答by Hans Passant

Right now, .NET doesn't support sections (aka Memory Mapped Files). It will soon, the 4.0 version has the System.IO.MemoryMappedFiles namespace. There is a good reason it took so long and also the reason you are not going to be happy with this addition. Using pointers is mandatory in MMFs, the shared memory is made available at a specific address. To share a value, you'll have to write it to a specific address.

现在,.NET 不支持节(又名内存映射文件)。很快,4.0 版本就有了 System.IO.MemoryMappedFiles 命名空间。花了这么长时间是有充分理由的,也是您对这个添加不满意的原因。在 MMF 中必须使用指针,共享内存在特定地址处可用。要共享值,您必须将其写入特定地址。

Pointers are however fundamentally incompatible with the managed memory model. Objects are created in a garbage collected heap, the collector moves them around as needed to keep the heap compacted. In a managed language, you have a reference to such an object, also knows as a "tracking handle". The C/C++ equivalent is a pointer, but it is one with bells on, the garbage collector can always find it back and update its value. The CLR does support the notion of "pinning", it converts a reference to a pointer. It implements this by marking the object as unmoveable. That however doesn't help implement shared memory through an MMF, the object is pinned in the GC heap instead of the virtual memory address where the MMF view is located.

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

To make an MMF work, the object needs to be copied from the GC heap to the shared memory. That requires serialization. The .NET 4.0 class is named MemoryMappedViewStream. You probably can see where this is going, this is indistinguishable from using a named pipe or a socket. Getting data in and out of an MMF takes the same amount of effort. An MMF is merely slightly more efficient because the underlying buffer is not in the kernel memory pool.

要使 MMF 工作,需要将对象从 GC 堆复制到共享内存。这需要序列化。.NET 4.0 类名为 MemoryMappedViewStream。您可能会看到这是怎么回事,这与使用命名管道或套接字没有区别。将数据输入和输出 MMF 需要付出相同的努力。MMF 只是稍微高效一点,因为底层缓冲区不在内核内存池中。

You can break the rulez and do so today. You can P/Invoke the CreateFileMapping, OpenFileMapping and MapViewOfFile you need to create an MMF. And use the unsafe keyword so you can create pointers. You'll need to use value types (like struct) for the shared memory elements or use the Marshal class.

你可以打破规则,今天就这样做。您可以 P/Invoke 创建 MMF 所需的 CreateFileMapping、OpenFileMapping 和 MapViewOfFile。并使用 unsafe 关键字来创建指针。您需要为共享内存元素使用值类型(如结构)或使用 Marshal 类。

回答by Lars Truijens

IPC

工控机

If you are talking about Inter Process Communication. There are several possibilities like using tcp/udp sockets, mailslots, named pipes, memory mapped files, windows messages, etc.

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

.Net also offers some higher level IPC like .Net remotingand WCFwhich use the previous mentioned techniques. You can read more about it here.

.Net 还提供了一些更高级别的 IPC,如.Net 远程处理WCF,它们使用前面提到的技术。您可以在此处阅读更多相关信息。

Memory Mapped Files

内存映射文件

If you really want to share a block of memory instead of communication then maybe memory mapped files are what you want. .Net 4.0 has MemoryMappedFilefor that. If you don't or can't use .Net 4.0 you could implement it yourself as in this win32 example. Or you could try thiscode or see if you can use MemoryMappedFileStream mentioned hereand here. Or use this FileMapclass.

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

回答by Adam Matan

Use a named pipe.

使用命名管道

It's a mechanism that allows one process to write sequential data into a stream, from which the other process can read.

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

Note that named pipe only allow sequential read. If you need to use more elaborated queries, you might want to use client-server architecture. In this case, the reader process queries the other process for information using network sockets.

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

回答by devdimi

As already mentioned use Memory Mapped Files. Implementation for .NET < 4 available at: http://github.com/tomasr/filemap/
I have used and it works flawless. You may have some security issues when sharing between elevated/not elevated processes - the solution is to initialize the memory mapped file in the elevated process and set its security attributes accordingly.

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