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

Shu*_*eng 4 linux process debian namespace containers

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

但是,如果在'ing之前nsenter已经调用了,为什么还需要系统调用来确保子进程也将在输入的命名空间中?setnsexecfork

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.
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

Ste*_*itt 7

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

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

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

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

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

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

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

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