2

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

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

4

6 回答 6

8

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

于 2009-03-30T15:25:20.827 回答
8

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

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

我已经使用了各种带有偏移智能指针的复杂数据结构,它就像一个魅力。

于 2009-03-30T15:29:17.760 回答
3

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

在过程 1 中:

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

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

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

在过程 2 中:

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

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

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

尽管这些函数看起来很简单,但如果未正确选择标志,则行为会很棘手。如果您希望读取或写入共享内存,请PAGE_EXECUTE_READWRITECreateFileMapping().

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

最好在其中指定FALSE(不要从父进程继承句柄),OpenFileMapping()因为这样可以避免混淆。

于 2012-06-21T03:56:34.747 回答
2

对于 Windows,您可以获得共享内存以在 2 个进程上使用相同的地址。它可以通过多种技术实现。

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

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

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

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

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

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

于 2009-05-29T10:40:19.607 回答
0

您可以使用指针编组。

于 2009-03-30T15:28:52.970 回答
0

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

于 2009-03-30T15:37:26.990 回答