【问题标题】:Is fork() copy-on-write a stable exposed behavior that can be used to implement read-only shared memory?fork() copy-on-write 是一种稳定的暴露行为,可用于实现只读共享内存吗?
【发布时间】:2010-09-08 15:46:04
【问题描述】:

fork() 的手册页声明它不会复制数据页,它会将它们映射到子进程并放置一个写时复制标志。是这种行为吗:

  • 在不同的 Linux 版本之间保持一致?
  • 考虑了实施细节,因此可能会改变?

我想知道我是否可以使用 fork() 作为一种廉价获取共享只读内存块的方法。如果内存是物理复制的,那将是相当昂贵的 - 有很多分叉正在进行,并且数据区域足够大 - 但我希望不会......

【问题讨论】:

    标签: linux fork


    【解决方案1】:

    在没有 MMU(内存管理单元)的机器上运行的 Linux 将在 fork() 上复制所有进程内存。

    但是,这些系统通常非常小而且是嵌入式的,您可能不必担心它们。

    Apache的fork模型等很多服务,使用initialize和fork()方法来共享初始化的数据结构。

    您应该知道,如果您使用 Perl 和 Python 等使用引用计数变量或 C++ shared_ptr 的语言,则此模型将不起作用。它不起作用,因为随着引用计数的上下调整,内存变得不共享并被复制。

    这会在尝试使用初始化和分叉模型的 Perl 守护程序(如 SpamAssassin)中导致大量内存使用。

    【讨论】:

    • 要点,但我不是针对那些。这是一个普通的托管 Web 服务器环境。
    【解决方案2】:

    是的,您当然可以在 MMU-Linux 内核上依赖它;这几乎就是一切。

    但是,页面大小并不相同。

    可以通过使用 mmap() 创建一个匿名映射——一个不受物理文件支持的映射,为分叉进程显式创建一个共享内存区域。在 fork 上,该区域将始终保持共享(前提是孩子没有取消映射它,或者在同一地址映射其他东西)。如果需要,您可以将其保护为只读。

    使用(例如)malloc 分配的内存很容易最终与非只读的东西共享一个页面,这意味着当另一个结构被修改时它无论如何都会被复制。这包括 malloc 实现使用的内部结构。因此,您可能希望为此目的映射一个特定区域并从中进行分配。

    【讨论】:

      【解决方案3】:

      你能相信所有 Linux 版本都是这样的吗?不。但是你可以相信那些不使用甚至更快方法的人。

      因此,您应该使用该功能并依赖它,并在遇到性能问题时重新考虑您的决定。

      【讨论】:

      • 你能解释一下不同的、更快的方法的本质吗?这是基于系统的一般意识形态的猜测,还是基于扎实的知识?
      • Linux 黑客总是希望让事情变得更快、更好、更小。例如,大多数 Linux 版本用更少的代码行做更多的事情。所以他们不太可能放弃对写时复制的支持,除非出现更好的东西(这在当前的 CPU 架构中不太可能)。
      【解决方案4】:

      这种方法的成功取决于您对自己强加的“只读”限制的坚持程度。父母和孩子都必须遵守这个规定,否则记忆会被复制。

      但是,这可能不是您想象的灾难。内核可以复制小至单个页面(通常为 4 KB)来实现 CoW 语义。典型的 Linux 服务器会使用更复杂的东西,比如slab allocator,因此复制的区域可能会更大。

      主要的一点是,这与程序的内存使用概念是分离的。如果您malloc() 1 GB 的 RAM,分叉出一个孩子,而孩子只更改该内存块的第一个字节,则不会复制整个 1 GB 块。可能只复制一页,直到包含第一个字节的平板大小。

      【讨论】:

        【解决方案5】:

        是的

        所有 linux 发行版都使用相同的内核,尽管版本和发行版略有不同。

        另一个底层 fork(2) 实现不太可能很快会更快,因此可以肯定的是,写时复制将继续作为机制。也许不会永远,但肯定会持续多年。

        当然,一些主要的软件系统(例如,Phusion Passenger)以您想要的相同方式使用 fork(2),因此您不会是唯一利用 CoW 的人。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-30
          • 2021-12-04
          • 2013-03-06
          • 2012-10-26
          • 2012-04-26
          • 2011-02-10
          • 1970-01-01
          • 2013-04-27
          相关资源
          最近更新 更多