【问题标题】:windows - plain shared memory between 2 processes (no file mapping, no pipe, no other extra)windows - 2个进程之间的普通共享内存(没有文件映射,没有管道,没有其他额外的)
【发布时间】:2018-10-08 19:37:11
【问题描述】:

如何拥有一个独立的内存部分,它根本不支持任何文件或额外的管理层(如管道),并且可以在同一台 Windows 机器上的两个专用进程之间共享?

大部分文章将我指向 CreateFileMapping 的方向。让我们从那里开始:

使用 hFile=INVALID_HANDLE_VALUE 的 CreateFileMapping 实际上如何工作? 根据

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366537(v=vs.85).aspx

它 "...创建一个指定大小的文件映射对象,该对象由系统分页文件支持,而不是由文件系统中的文件支持..."

假设我在 CreateFileMapping 映射的内存中写入了一些内容,其中 hFile=INVALID_HANDLE_VALUE。在什么条件下这个内容会被写入磁盘上的页面文件?

此外,我对使用共享内存的动机的理解是保持性能和优化。为什么是“创建命名共享内存”一文 (https://msdn.microsoft.com/de-de/library/windows/desktop/aa366551(v=vs.85).aspx) 指 CreateFileMapping,如果没有单一的属性组合,这将阻止写入文件,例如页面文件?

回到最初的问题:恐怕 CreateFileMapping 还不够好......那么什么会起作用?

【问题讨论】:

  • 您是否知道您的进程使用的所有内存要么是直接文件映射,要么由分页文件支持?使用malloc 得到的东西,甚至堆栈本身都属于第二类。
  • 相信操作系统,它只会在必要时将数据交换到磁盘。

标签: c windows shared-memory


【解决方案1】:

您误解了系统页面文件“支持”内存的含义。 (不要难过;Raymond Chen 将您从 MSDN 引用的文本描述为“one of the most misunderstood sentences in the Win32 documentation”。)几乎所有计算机的内存都由磁盘上的something“支持”;只有内核专门使用并且尽可能少的“非分页池”不是。如果一个页面不是由一个普通的命名文件支持的,那么它是由系统分页文件支持的。除非需要,否则操作系统不会将页面写入系统页面文件,但如果确实需要,它可以。

此架构旨在确保进程在无事可做时可以完全从 RAM 中“分页”。这在过去比现在重要得多,但它仍然很有价值;典型的 Windows 桌面会有几十个进程“空闲”等待可能永远不会发生的事件(例如,需要假脱机打印作业)。这些进程可以被调出,内存可以用于更具建设性的用途。

CreateFileMappinghfile=INVALID_HANDLE_VALUE 实际上就是你想要的。只要共享内存的进程正在积极地使用它,它就会一直驻留在 RAM 中,并且不会出现性能问题。如果他们闲置,是的,它可能会被分页,但这很好,因为他们没有对它做任何事情。

可以指示系统不要分页出一块内存;这就是VirtualLock 的用途。但它的目的是用于包含 secret 信息的小块内存,将其写入页面文件可能会泄露秘密。 MSDN 页面警告您“每个版本的 Windows 都有一个进程可以锁定的最大页面数的限制。这个限制是故意很小以避免严重的性能下降。”

【讨论】:

  • 使用这样的系统页面文件(指定 INVALID_HANDLE_VALUE),您将无法在多个进程之间共享。您可以在 .DLL 中创建一个共享部分并将该库加载到多个进程中,但只能以这种方式共享静态大小的对象(您可以在共享部分中有一个 char * 并且指针本身将在进程之间共享,但是但是除非它故意指向已加载到相同基地址的内存,否则该指针引用将有所不同)。
  • @SornelHaetir:“使用这样的系统页面文件(指定 INVALID_HANDLE_VALUE)你将无法在多个进程之间共享”假,你只需要传递一个名称作为最后一个参数.
  • @SornelHaetir,文件映射实际上是一个 Section 对象,可以命名(全局或会话本地)并保护它,因此任何具有访问权限的进程都可以打开它。除其他外,Section 描述了原型页表条目块,它们充当进程 PTE 和页框数据库之间的间接层。当进程中的页面无效时,内存管理器可以使用原型 PTE 中的页帧号来使进程 PTE 有效。如果原型无效,那么在这种情况下,它将引用磁盘上页面文件中的页面偏移量。
  • @zwol,谢谢你的澄清。我正在绝望地寻找任何信息,如果我现在使用 hfile=INVALID_HANDLE_VALUE 进行 CreateFileMapping,windows 通过将任何类型的至少管理信息写入页面文件(例如,以同步方式维护页面文件内部目录)来保持自身。在你回答之后,我认为不会。
  • @Quicker,内存是按页访问的(例如 x64 中每页 4 KiB),每个进程都有一个页表,每页有一个条目。如果 PTE 有效,则硬件内存管理单元 (MMU) 使用它将页面中的虚拟地址转换为其相应的物理内存页面帧号。如果它无效,则故障由操作系统内存管理器在软件中处理。对于共享内存,无效的 PTE 将指向一个公共原型 PTE,而该原型 PTE 又可能是有效的并指向物理内存页面,或者它可能是无效的(被换出)并指向磁盘上页面文件中的偏移量。
猜你喜欢
  • 2019-07-19
  • 2023-03-27
  • 2017-05-06
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 2018-03-26
  • 2011-01-02
  • 1970-01-01
相关资源
最近更新 更多