简体   繁体   English

在 C++ 中寻找 Windows 基于 RAM 的共享 memory 解决方案

[英]looking for Windows RAM-based shared memory solution in C++

I'm facing a situation where I need to pass up to several hundreds of megabytes of memory from one process to another.我面临一种情况,我需要将多达数百兆字节的 memory 从一个进程传递到另一个进程。 Right now I'm doing it via files and it's too slow.现在我正在通过文件来做这件事,而且太慢了。 I guess that to make it quicker, those files should be written directly to RAM and be accessible from another process.我想为了让它更快,这些文件应该直接写入 RAM 并且可以从另一个进程访问。 No fancy synchronization required.不需要花哨的同步。 One process would create shared memory objects and would fill them with data.一个进程将创建共享的 memory 对象并用数据填充它们。 The other process would read and remove them.另一个进程将读取并删除它们。 However I've done a quick research and it seems like you can't share memory in RAM in Windows - the shared memory is backed by either a file or paging file.但是,我进行了快速研究,似乎您无法在 Windows 的 RAM 中共享 memory - 共享的 memory 由文件或分页文件支持。 The docs of boost::interprocess confirm this. boost::interprocess 的文档证实了这一点。 Where is the speed up then if the shared memory implementation still uses disk?如果共享 memory 实现仍然使用磁盘,那么速度在哪里? Is there any C++ library that uses RAM-based shared memory?是否有任何使用基于 RAM 的共享 memory 的 C++ 库?

EDIT: I made some further reading: 1. from boost::interprocess docs: "as the operating system has to synchronize the file contents with the memory contents, memory-mapped files are not as fast as shared memory. " 2. from http://msdn.microsoft.com/en-us/library/ms810613.aspx : "A memory-mapped file can also be mapped by more than one application simultaneously. This represents the only mechanism for two or more processes to directly share data in Windows NT."编辑:我做了一些进一步的阅读:1.来自 boost::interprocess docs:“由于操作系统必须将文件内容与 memory 内容同步,内存映射文件不如共享 memory 快。” 2.来自Z80794B3AEC70 ://msdn.microsoft.com/en-us/library/ms810613.aspx :“一个内存映射文件也可以同时被多个应用程序映射。这是两个或多个进程直接共享数据的唯一机制在 Windows NT 中。”

I think that here is a fundamental misunderstanding: you think that, if you create a file mapping backed by the paging file, it will be as slow as actually writing stuff on disk.我认为这是一个根本性的误解:您认为,如果您创建一个由页面文件支持的文件映射,它将与实际在磁盘上写入内容一样慢。

This is definitely not the case: the meaning of "backed by the paging file" in the documentation means that the shared memory in general resides in memory, but it has a reserved place in the paging file to write such data if there's not enough free physical memory and the virtual memory manager needs to swap out memory pages.肯定不是这样的:文档中“由分页文件支持”的意思是指共享的memory一般驻留在memory中,但是如果没有足够的空闲,它在分页文件中有一个保留的位置来写入这些数据物理 memory 和虚拟 memory 管理器需要换出 memory 页面。

This is not really clear from the documentation but the File Mapping page on MSDN confirms:这在文档中并不是很清楚,但 MSDN 上的文件映射页面证实:

[...] It is backed by the file on disk. [...] 它由磁盘上的文件支持。 This means that when the system swaps out pages of the file mapping object , any changes made to the file mapping object are written to the file.这意味着当系统换出文件映射 object 的页面时,对文件映射 object所做的任何更改都会写入文件。 When the pages of the file mapping object are swapped back in, they are restored from the file.当文件映射 object 的页面被换回时,它们会从文件中恢复。

Notice that this applies to shared memory backed by the paging file as well as memory backed by regular files (the VMM guarantees that the various views are kept coherent).请注意,这适用于由分页文件支持的共享 memory 以及由常规文件支持的 memory(VMM 保证各种视图保持一致)。

Incidentally, this is how "regular" (=virtual) memory in user processes works: every bit of allocated memory can be swapped out to the paging file if it's not currently used and the system need to use physical memory for other stuff (eg making memory pages that are used at the moment available to your/another application). Incidentally, this is how "regular" (=virtual) memory in user processes works: every bit of allocated memory can be swapped out to the paging file if it's not currently used and the system need to use physical memory for other stuff (eg making memory 页面当前可用于您/其他应用程序)。

There's nothing wrong with being backed by a file -- under memory pressure, the data has to go somewhere, and your choices are:由文件支持并没有错——在 memory 压力下,数据必须在 go 某处,您的选择是:

  • treat the memory as sacred data that cannot be paged or dropped将 memory 视为无法分页或删除的神圣数据

    Likely to only create much worse memory pressure problems, but good choice for some embedded systems where the entire runtime environment of the system can be very well controlled.可能只会造成更糟糕的 memory 压力问题,但对于一些可以很好地控制系统的整个运行时环境的嵌入式系统来说是不错的选择。

  • drop the memory放下 memory

    Obviously not suitable to all data.显然不适合所有数据。 Cached contents?缓存内容? Maybe.也许。 Original photos?原始照片? Probably not.可能不是。

  • page the memory to disk将 memory 分页到磁盘

    Good generic choice!通用的好选择!

Are you seeing memory pressure when using a shared-memory tool?使用共享内存工具时,您是否看到 memory 压力? Add more RAM or figure out how to shrink your systems.添加更多 RAM 或弄清楚如何缩小系统。 :) :)

As far as I know you have essentially 2 Options here.据我所知,这里基本上有 2 个选项。

1)You create a DLL and use the data_seg pragma and load the DLL in both of your processes. 1)您创建一个 DLL 并使用 data_seg pragma 并在两个进程中加载 DLL。 This has HUGE drawbacks which are explained in detail here: http://msdn.microsoft.com/en-us/library/h90dkhs0(v=vs.80).aspx这有巨大的缺点,这里详细解释: http://msdn.microsoft.com/en-us/library/h90dkhs0(v=vs.80).aspx

The most important drawbacks are: The space has to be initialized statically and are stored in the data segment of the compiled DLL, meaning that if you want to share hundreds of MBs using this method then your DLL is going to be hundreds of MBs big.最重要的缺点是:空间必须静态初始化并存储在已编译的 DLL 的数据段中,这意味着如果您想使用此方法共享数百 MB,那么您的 DLL 将有数百 MB 大。

2)There's nothing wrong with using regular Memory-mapped files though as they are cached anyways. 2)使用常规的内存映射文件没有任何问题,因为它们无论如何都会被缓存。 You can even use the Systems pagefile to store the data as described in this article: http://msdn.microsoft.com/en-us/library/ms810613.aspx您甚至可以使用系统页面文件来存储本文所述的数据: http://msdn.microsoft.com/en-us/library/ms810613.aspx

I actually tested this example [1] of Inter-process communication With a 1 GiB memory-mapped file and can confirm that nothing was written to disk even after filling the whole GiB with data.我实际上测试了这个使用 1 GiB 内存映射文件的进程间通信示例 [1],并且可以确认即使在用数据填充整个 GiB 之后也没有任何内容写入磁盘。

[1] http://msdn.microsoft.com/en-us/library/aa366551(v=vs.85).aspx [1] http://msdn.microsoft.com/en-us/library/aa366551(v=vs.85).aspx

I would still suggested memory mapped files instead of the approach I will mention.我仍然会建议 memory 映射文件,而不是我将提到的方法。

If you really want to read from another process memory , use Win32 API ReadProcessMemory() .如果你真的想从另一个进程中读取 memory ,请使用Win32 API ReadProcessMemory()

If you are paranoid on keeping data in RAM, there are Unix mlock() equivalents in MS Windows VirtualLock()如果您对将数据保存在 RAM 中感到偏执,那么在 MS Windows VirtualLock()中有 Unix mlock() 等效项

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM