这是一个安全的方式与subprocess共享只读内存?

我想分配和初始化一个相当大的连续内存块(〜1GB),然后将其标记为只读并分叉多个(比如几十个)subprocess将使用它,而不使自己的内存副本机器将没有足够的内存这个)。

我正确的想,如果我malloc内存像往常一样,然后将其标记为mprotect(addr, size, PROT_READ) ,然后fork ,这将允许subprocess安全地使用内存,而不会导致它复制? (提供我保证在mprotect调用之后没有任何东西试图写入分配的内存)。

编辑:感谢所有的答案。

一个后续问题 – 我正在计划使用shmget ,但是我认为它使用了mm ,因此将被限制为较小的分配(参见本页的限制部分 )。 例如/proc/sys/kernel/shmmax是我使用这个服务器上的32MB。 但是我想要1GB的连续内存。 我错了这个限制吗?

男人mprotect

实现将要求addrsysconf()返回的页面大小的倍数。

如果映射不是通过调用mmap()来建立的,则此函数的行为是未指定的。

  1. mprotect只能在页面上工作,而不是任意的字节范围,所以一般malloc是不合适的。 posix_memalign可能有帮助,但…
  2. 虽然它现在可能在你的系统上工作,但是你 mprotect你自己没有的东西。 改用mmap(0, pages*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0)

由于这个原因,任何子进程都可以调用mprotect()来删除保护并开始在那里写。 如果页面没有被复制,将违反fork()的原则。

即使这样写入时拷贝被用于分叉进程,我也不会认为标准中有这样的地方(例如,POSIX并没有说它是copy-on-write)。

您可以使用标准的措施来共享内存,而不是使用非标准的行为。 例如,POSIX共享内存与shm_open和随之而来的mmap (正如在评论中指出的,并在ephemient的解释中)。 文件描述符将通过分叉来保存。

无需将其标记为只读,只需让您的子进程保持独立。

如果父母和孩子都不写信,它应该保持共享。 如果你不想改变它,那很好。

如果要写入,则需要使用带有MAP_SHARED的mmap。

你假设内核将进行写时拷贝优化,而不是复制mprotect页面。 我不会指望它。 malloc -ed内存中有各种各样的元数据 – 保护页面等等,只有Ulrich Drepper知道在libc里面发生了什么:)

在磁盘文件中准备数据并将它们mmap到所有进程或者使用正常的POSIX shm_open路径可能会更容易,更安全。

我的理解是肯定的,因为Linux使用传递给子进程的内存页面的写入时复制机制。

你可以这样做。

另一种方法是使用mmap() 。

另一种方法是使用POSIX共享内存( shm_open() ); 另一个主要的选择是System V共享内存( shmget() , shmat() )。 正式的共享内存系统的一个优点是你的父进程可以创建内存,然后不相关的进程可以连接到它 – 如果这是有益的。