在 C++ 中寻找基于 Windows RAM 的共享内存解决方案
我面临着一种情况,我需要将多达数百兆字节的内存从一个进程传递到另一个进程。现在我正在通过文件来完成它,但速度太慢了。 我想为了更快,这些文件应该直接写入 RAM 并且可以从另一个进程访问。不需要花哨的同步。一个进程将创建共享内存对象并用数据填充它们。另一个进程将读取并删除它们。不过,我进行了一项快速研究,似乎您无法在 Windows 中共享 RAM 中的内存 - 共享内存由文件或分页文件支持。 boost::interprocess 的文档证实了这一点。如果共享内存实现仍然使用磁盘,那么速度在哪里?有没有使用基于 RAM 的共享内存的 C++ 库?
编辑:我做了一些进一步的阅读: 1.来自 boost::interprocess 文档: “由于操作系统必须将文件内容与内存内容同步,因此内存映射文件的速度不如共享内存。” 2.来自 http://msdn.microsoft.com/en-us/library/ ms810613.aspx: “内存映射文件也可以同时被多个应用程序映射。这是 Windows NT 中两个或多个进程直接共享数据的唯一机制。”
I'm facing a situation where I need to pass up to several hundreds of megabytes of memory from one process to another. 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. No fancy synchronization required. One process would create shared memory objects and would fill them with data. 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. The docs of boost::interprocess confirm this. Where is the speed up then if the shared memory implementation still uses disk? Is there any C++ library that uses RAM-based shared memory?
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."
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为这是一个根本性的误解:您认为,如果您创建由分页文件支持的文件映射,那么它会像实际在磁盘上写入内容一样慢。
绝对不是这种情况:文档中“由分页文件支持”的含义意味着共享内存通常驻留在内存中,但它在分页文件中保留了一个位置,以便在没有足够的可用空间时写入此类数据物理内存和虚拟内存管理器需要交换内存页面。
文档中并不清楚这一点,但 文件MSDN 上的映射页面确认:
请注意,这适用于由分页文件支持的共享内存以及由常规文件支持的内存(VMM 保证各种视图保持一致)。
顺便说一句,这就是用户进程中“常规”(=虚拟)内存的工作原理:如果当前未使用分配的内存,并且系统需要将物理内存用于其他内容(例如,使当前使用的内存页可供您/另一个应用程序使用)。
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.
This is not really clear from the documentation but the File Mapping page on MSDN confirms:
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).
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 (e.g. making memory pages that are used at the moment available to your/another application).
由文件支持并没有什么问题——在内存压力下,数据必须到达某个地方,您的选择是:
将内存视为无法分页或删除的神圣数据< /p>
可能只会造成更严重的内存压力问题,但对于某些嵌入式系统来说是不错的选择,因为系统的整个运行时环境可以得到很好的控制。
删除内存
显然并不适合所有数据。缓存内容?或许。原照片?可能不会。
将内存分页到磁盘
良好的通用选择!
使用共享内存工具时您是否遇到内存压力?添加更多 RAM 或找出如何缩小系统规模。 :)
There's nothing wrong with being backed by a file -- under memory pressure, the data has to go somewhere, and your choices are:
treat the memory as sacred data that cannot be paged or dropped
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.
drop the memory
Obviously not suitable to all data. Cached contents? Maybe. Original photos? Probably not.
page the memory to disk
Good generic choice!
Are you seeing memory pressure when using a shared-memory tool? Add more RAM or figure out how to shrink your systems. :)
据我所知,你基本上有两个选择。
1) 创建一个 DLL 并使用 data_seg pragma 并在两个进程中加载该 DLL。这有巨大的缺点,详细解释如下:
http://msdn.microsoft.com/en- us/library/h90dkhs0(v=vs.80).aspx
最重要的缺点是:该空间必须静态初始化并存储在编译后的DLL的数据段中,这意味着如果你想共享如果使用此方法,您的 DLL 将达到数百 MB。
2)使用常规内存映射文件并没有什么问题,因为它们无论如何都会被缓存。您甚至可以使用系统页面文件来存储数据,如本文所述:
http://msdn.microsoft.com/en-us/library/ms810613.aspx
我实际测试了这个进程间通信的示例[1]
使用 1 GiB 内存映射文件,即使在用数据填充整个 GiB 后也可以确认没有任何内容写入磁盘。
[1] http://msdn.microsoft.com /en-us/library/aa366551(v=vs.85).aspx
As far as I know you have essentially 2 Options here.
1)You create a DLL and use the data_seg pragma and load the DLL in both of your processes. This has HUGE drawbacks which are explained in detail here:
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.
2)There's nothing wrong with using regular Memory-mapped files though as they are cached anyways. 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
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] http://msdn.microsoft.com/en-us/library/aa366551(v=vs.85).aspx
我仍然建议内存映射文件而不是我将提到的方法。
如果您确实想从另一个进程内存读取,请使用Win32 API ReadProcessMemory()。
如果您对将数据保存在 RAM 中感到偏执,MS Windows 中有 Unix mlock() 等效项 VirtualLock()
I would still suggested memory mapped files instead of the approach I will mention.
If you really want to read from another process memory, use Win32 API ReadProcessMemory().
If you are paranoid on keeping data in RAM, there are Unix mlock() equivalents in MS Windows VirtualLock()