在Linux中,多个进程使用文件指针读取文件时使用的共享虚拟内存



我写了一个C++程序,它使用文件指针读取文件。我需要同时运行多个进程。由于文件的大小可能很大(100MB~),为了减少多个进程中的内存使用,我认为我需要使用共享内存。(例如像boost::interprocess::shared_memory_object这样的IPC库)

但它真的需要吗?因为我认为,如果多个进程读取同一个文件,那么每个进程的虚拟内存就会通过页表映射到文件的同一物理内存。

我读了一篇Linux文档,他们说,

共享虚拟内存

尽管虚拟内存允许进程具有单独的(虚拟)地址空间,有时您需要共享进程记忆力例如,系统中可能有几个进程运行bash命令shell。而不是几份bash,每个进程中有一个处理虚拟地址空间,最好在物理内存中只有一个副本,并且所有进程都在运行bash共享它。动态库是执行多个进程之间共享的代码。共享内存可以也可用作进程间通信(IPC)机制两个或多个进程通过所有进程共用的存储器交换信息他们中的一个。Linux支持Unix TM System V共享内存IPC。

此外,维基表示,

在计算机软件中,共享内存要么是

  • 进程间通信(IPC)的一种方法,即在同时运行的程序之间交换数据的一种方式。一个过程将在RAM中创建一个其他进程可以访问的区域,或者
  • 一种节省内存空间的方法,通过将通常是一段数据副本的访问定向到一个实例相反,通过使用虚拟内存映射或显式支持有问题的程序。这最常用于共享库以及XIP

因此,我真正好奇的是,OS级别是否支持共享虚拟内存?

提前谢谢。

关于您的第一个问题-如果您希望数据可以由多个进程访问而不会重复,那么您肯定需要某种共享存储。

在C++中,我肯定会使用boost的shared_memory_object。这是在流程之间共享(大)数据的有效选项,并且有很好的文档和示例(http://www.boost.org/doc/libs/1_55_0/doc/html/interprocess/sharedmemorybetweenprocesses.html)。

使用mmap()是一种更低级的方法,通常在C中使用。要将其用作IPC,您必须使映射区域共享。从…起http://man7.org/linux/man-pages/man2/mmap.2.html:

MAP_SHARED

共享此映射。映射的更新对可见映射此文件并执行的其他进程到底层文件。该文件实际上可能不是直到调用msync(2)或munmap()。

在该页面上还有一个将文件映射到共享内存的示例。

无论哪种情况,都至少有两件事需要记住:

  • 如果有多个进程修改共享数据,则需要同步。

  • 不能使用指针,只能使用从映射区域开始的偏移量。以下是boost文档的解释:

如果多个进程映射同一个文件/共享内存,那么每个进程的映射地址肯定会不同。由于每个进程可能以不同的方式使用其地址空间(例如,分配或多或少的动态内存),因此无法保证文件/共享内存将映射到同一地址。

如果两个进程将同一对象映射到不同的地址,这将使在该内存中使用指针无效,因为指针(绝对地址)只对写入它的进程有意义。解决方案是使用对象之间的偏移(距离)而不是指针:如果一个进程将两个对象放在同一共享内存段中,在另一个进程中,每个对象的地址将不同,但它们之间的距离(以字节为单位)将相同

关于操作系统支持-是的,碎片内存是操作系统特有的功能。在Linux中,mmap()实际上是在内核和模块中实现的,可以用于在用户和内核空间之间传输数据。

Windows也有它的细节:

Windows共享内存创建与便携式共享内存创建有点不同:创建对象时必须指定段的大小,而不能像共享内存对象那样通过截断来指定。请注意,当连接到共享内存的最后一个进程被破坏时,共享内存也会被破坏,因此本机windows共享内存不会持久。

你的问题没有意义。

我想我需要使用共享内存。(例如,像boost::interprocess::shared_memory_object).这样的IPC库

如果使用共享内存,则内存是共享的。

我认为如果多个进程读取同一个文件,那么每个进程的虚拟内存就会通过页表映射到文件的同一物理内存。

现在您讨论的是内存映射I/O。这不是一回事。然而,更可能的是,在这种情况下,是您所需要的

最新更新