在 Windows 下使用共享内存。如何传递不同的数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/697664/
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-15 12:14:23  来源:igfitidea点击:

Using shared memory under Windows. How to pass different data

c++windowsshared-memory

提问by asdrubael

I currently try to implement some interprocess communication using the Windows CreateFileMappingmechanism. I know that I need to create a file mapping object with CreateFileMapping first and then create a pointer to the actual data with MapViewOfFile. The example then puts data into the mapfile by using CopyMemory.

我目前尝试使用 Windows CreateFileMapping机制实现一些进程间通信。我知道我需要先用 CreateFileMapping 创建一个文件映射对象,然后用 MapViewOfFile 创建一个指向实际数据的指针。该示例然后使用 CopyMemory 将数据放入映射文件中。

In my application I have an image buffer (1 MB large) which I want to send to another process. So now I inquire a pointer to the image and then copy the whole image buffer into the mapfile. But I wonder if this is really necessary. Isn't it possible to just copy an actual pointer in the shared memory which points to the image buffer data? I tried a bit but didn't succeed.

在我的应用程序中,我有一个图像缓冲区(1 MB 大),我想将其发送到另一个进程。所以现在我查询一个指向图像的指针,然后将整个图像缓冲区复制到映射文件中。但我想知道这是否真的有必要。难道不能只复制共享内存中指向图像缓冲区数据的实际指针吗?我尝试了一点,但没有成功。

回答by Zifre

Different processes have different address spaces. If you pass a valid pointer in one process to another process, it will probably point to random data in the second process. So you will have to copy all the data.

不同的进程有不同的地址空间。如果您将一个进程中的有效指针传递给另一个进程,它可能会指向第二个进程中的随机数据。因此,您必须复制所有数据。

回答by Jason S

I stronglyrecommend you use Boost::interprocess. It has lots of goodies to manage this kind of stuff & even includes some special Windows-only functions in case you need to interoperate w/ other processes that use particular Win32 features.

强烈建议您使用Boost::interprocess。它有很多好东西来管理这类东西,甚至包括一些特殊的 Windows 专用功能,以防您需要与其他使用特定 Win32 功能的进程进行互操作。

The most important thing is to use offset pointersrather than regular pointers. Offset pointers are basically relative pointers (they store the difference between where the pointer is and where the thing pointed to is). This means that even if the two pointers are mapped to different address spaces, as long as the mappings are identical in structure then you are fine.

最重要的是使用偏移指针而不是常规指针。偏移指针基本上是相对指针(它们存储指针所在位置和指向的事物所在位置之间的差异)。这意味着即使两个指针映射到不同的地址空间,只要映射结构相同,就可以了。

I've used all kinds of complicated data structures with offset smart pointers and it worked like a charm.

我已经使用了各种带有偏移智能指针的复杂数据结构,它的工作原理非常棒。

回答by Vinaykumar

Shared Memory doesn't mean sending and receiving of Data. Its a memory created for number of processes without violation. For that you have to follow some mechanisms like locks so that the data will not corrupt.

共享内存并不意味着发送和接收数据。它是为没有违反的进程数创建的内存。为此,您必须遵循一些机制,例如锁,以便数据不会损坏。

In process 1 :

在过程 1 中:

CreateFileMapping(): It will create the Shared Memory Block, with the name provided in last parameter, if it is not already present and returns back a handle (you may call it a pointer), if successful.

CreateFileMapping(): 它将创建共享内存块,使用最后一个参数中提供的名称,如果它不存在,并返回一个句柄(你可以称之为指针),如果成功。

MapViewOfFile(): It maps (includes) this shared block in the process address space and returns a handle (again u can say a pointer).

MapViewOfFile():它在进程地址空间中映射(包含)这个共享块并返回一个句柄(你也可以说是一个指针)。

With this pointer returned by MapViewOfFile()only you can access that shared block.

使用此指针返回的MapViewOfFile()只有您可以访问该共享块。

In process 2 :

在过程 2 中:

OpenFileMapping(): If the shared memory block is successfully created by CreateFileMapping(), you can use it with the same name (name used to create the shared memory block).

OpenFileMapping(): 如果通过 成功创建共享内存块,则CreateFileMapping()可以使用相同的名称(用于创建共享内存块的名称)。

UnmapViewOfFile(): It will unmap (you can remove the shared memory block from that process address space). When you are done using the shared memory (i.e. access, modification etc) call this function .

UnmapViewOfFile():它将取消映射(您可以从该进程地址空间中删除共享内存块)。当您使用完共享内存(即访问、修改等)后,调用此函数。

Closehandle(): finally to detach the shared memory block from process , call this with argument,handle returned by OpenFileMapping() or CreateFileMapping().

Closehandle(): 最后从进程中分离共享内存块,用参数调用它,句柄由 OpenFileMapping() 或 CreateFileMapping() 返回。

Though these functions look simple, the behaviour is tricky if the flags are not selected properly. If you wish to read or write shared memory, specify PAGE_EXECUTE_READWRITEin CreateFileMapping().

虽然这些函数看起来很简单,但如果标志选择不当,行为就会很棘手。如果您希望读取或写入共享内存,请PAGE_EXECUTE_READWRITECreateFileMapping().

Whenever you wish to access shared memory after creating it successfully, use FILE_MAP_ALL_ACCESSin MapViewOfFile().

每当您希望在成功创建共享内存后访问共享内存时,请使用FILE_MAP_ALL_ACCESSin MapViewOfFile()

It is better to specify FALSE(do not inherit handle from parent process) in OpenFileMapping()as it will avoid confusion.

最好指定FALSE(不要从父进程继承句柄),OpenFileMapping()因为它会避免混淆。

回答by RandomNickName42

You CANget shared memory to use the same addressover 2 processes for Windows. It's achieveable with several techniques.

CAN得到共享内存使用同一地址超过2个进程的Windows。它可以通过多种技术实现。

Using MapViewOfFileEx, here's the significant experpt from MSDN.

使用MapViewOfFileEx,这是来自 MSDN 的重要专家。

If a suggested mapping address is supplied, the file is mapped at the specified address (rounded down to the nearest 64K-boundary) if there is enough address space at the specified address. If there is not enough address space, the function fails.

Typically, the suggested address is used to specify that a file should be mapped at the same address in multiple processes. This requires the region of address space to be available in all involved processes. No other memory allocation can take place in the region that is used for mapping, including the use of the VirtualAlloc or VirtualAllocEx function to reserve memory.

If the lpBaseAddress parameter specifies a base offset, the function succeeds if the specified memory region is not already in use by the calling process. The system does not ensure that the same memory region is available for the memory mapped file in other 32-bit processes.

如果提供了建议的映射地址,则如果指定地址有足够的地址空间,则文件将映射到指定地址(向下舍入到最近的 64K 边界)。如果没有足够的地址空间,该功能将失败。

通常,建议地址用于指定文件应在多个进程中映射到同一地址。这要求地址空间区域在所有涉及的进程中都可用。在用于映射的区域中不能进行其他内存分配,包括使用 VirtualAlloc 或 VirtualAllocEx 函数来预留内存。

如果 lpBaseAddress 参数指定了一个基址偏移量,如果调用进程尚未使用指定的内存区域,则该函数将成功。系统不确保相同的内存区域可用于其他 32 位进程中的内存映射文件。

Another related technique is to use a DLL with a section marked Read + Write + Shared. In this case, the OS will pretty much do the MapViewOfFileEx call for you and for any other process which loads the DLL.

另一种相关技术是使用带有标记为 Read + Write + Shared 的部分的 DLL。在这种情况下,操作系统几乎会为您和加载 DLL 的任何其他进程执行 MapViewOfFileEx 调用。

You may have to mark your DLL to a FIXED load address, not relocateable etc.. naturally.

您可能必须将 DLL 标记为固定加载地址,不可重定位等。自然。

回答by Rob K

If it's possible, it would be best to have the image data loaded/generated directly into the shared memory area. This eliminates the memory copy and puts it directly where it needs to be. When it's ready you can signal the other process, giving it the offset into your shared memory where the data begins.

如果可能,最好将图像数据直接加载/生成到共享内存区域。这消除了内存副本并将其直接放在需要的位置。当它准备好时,您可以向另一个进程发送信号,将偏移量提供给数据开始的共享内存。

回答by Vinay

You can use Marshalling of pointers.

您可以使用指针编组。