【问题标题】:How is it that a child process that calls exec() right after forking wouldn't need a separate copy of the parent's address space?为什么在分叉后立即调用 exec() 的子进程不需要父地址空间的单独副本?
【发布时间】:2016-10-08 07:39:56
【问题描述】:

我正在阅读 Robert Love 的“Linux 内核开发,第二版”。 (是的,它有点过时了)。我从第 3 章:进程管理中了解到,在 COW(写时复制)中,父进程和子进程共享父进程的地址空间,直到其中一个进程写入地址空间。这是为了防止父地址空间在没有被写入时不必要的重复。

但是,它提到如果子进程在fork() 之后立即调用exec(),则不需要复制父进程的地址空间和页面并将其作为单独的副本提供给子进程。那就是我迷路的地方。

根据手册,“exec() 系列函数用新的进程映像替换当前进程映像。” 手册没有说明exec() 创建新地址新过程映像的空间。因此,如果子进程与其父进程共享地址空间,这是否意味着exec() 会将可执行映像加载到父进程的地址空间(与子进程共享)?

由于这意味着父地址空间将被覆盖,我不明白在fork() 之后执行exec() 的子进程如何不需要其父地址空间的单独副本来写入。我这里有什么遗漏吗?

【问题讨论】:

    标签: linux linux-kernel


    【解决方案1】:

    您甚至可以在没有写时复制机制的 vfork() 上阅读。它共享父进程的地址空间,并且在子进程存在之前怀疑父进程。这很有趣,让事情变得更加清晰。

    【讨论】:

      【解决方案2】:

      Copy-on-Write 机制意味着,子进程中的任何修改都不会影响父进程

      子进程调用exec 也不例外:它只更改子进程的地址空间,而不是父进程。

      【讨论】:

      • 确实如此。 exec() 将完全替换内存映射,但仅适用于调用进程。只有非内存映射资源存在:文件描述符(没有 CLOEXEC 标志)、当前目录、UID、GID 和朋友、权限等。
      • 那么这是否意味着孩子获得了一个单独的地址空间,它不包含父的内存映射资源,而只有非内存映射的资源(意味着没有那么多的复制完成了)?
      • 是的,确实如此。 fork() 的文档描述了哪些非内存映射资源与子共享。反过来,exec() 的文档描述了哪些资源保留在新进程映像中。
      • 好的,这非常清楚。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-05
      • 1970-01-01
      • 2014-07-28
      • 2021-11-26
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      相关资源
      最近更新 更多