为什么“nsenter”需要在“exec”之前调用“fork”以确保任何子级也将位于新进入的PID命名空间中?

为什么“nsenter”需要在“exec”之前调用“fork”以确保任何子级也将位于新进入的PID命名空间中?

我假设nsenter作为 的子进程运行的bash,利用setns系统调用来加入现有的命名空间,然后使用 执行指定的程序exec

但是,如果nsenter已经在 'ingsetns之前调用exec,为什么fork需要系统调用来确保子进程也位于输入的命名空间中?

man namespaces

setns(2)
      The setns(2) system call allows the calling process to join an
      existing namespace.  The namespace to join is specified via a
      file descriptor that refers to one of the /proc/[pid]/ns files
      described below.

man nsenter

...
-F, --no-fork
      Do not fork before exec'ing the specified program.  By
      default, when entering a PID namespace, nsenter calls fork
      before calling exec so that any children will also be in the
      newly entered PID namespace.

答案1

解释在“PID命名空间”部分给出man nsenter

子进程将有一组 PID 来与nsenter进程分开进行进程映射。 nsenter如果更改 PID 命名空间,则默认会分叉,以便新程序及其子程序共享相同的 PID 命名空间并且彼此可见。如果--no-fork使用,新程序将在不分叉的情况下执行。

(手册有些混乱;我已经清理了上面引用的部分,并且的下一个版本util-linux将包含修复程序.)

输入 PID 命名空间不会将当前进程移动到该命名空间,它只会导致在该命名空间中创建新的子进程。因此,当前进程(调用的进程setns)对于新命名空间中的子进程不可见。为了避免这种情况,nsenter输入新的命名空间,然后分叉,这会nsenter在新的命名空间中产生一个新的,然后调用exec;结果,执行的程序位于新的命名空间中。

另请参阅 PID 命名空间的描述man setns

如果FD指的是 PID 命名空间,其语义与其他命名空间类型有些不同:将调用线程与 PID 命名空间重新关联仅更改随后创建的调用者子进程将放置的 PID 命名空间;它不会更改调用者本身的 PID 命名空间。

您将在命名空间条目中看到这一点/proc/proc/.../ns有两个 PID 条目,pid(进程的命名空间)和pid_for_children(用于新子进程的命名空间)。

exec它本身不会创建新的进程。)

相关内容