我假设nsenter作为bash的子进程运行,它利用setns系统调用加入现有的命名空间,然后使用exec执行指定的程序。
但是,如果nsenter已经在exec'ing之前调用了setns,那么为什么需要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.发布于 2020-04-23 07:41:55
man nsenter的“PID命名空间”部分给出了解释:
子进程将有一组PID来处理与
nsenter进程分离的映射。默认情况下,如果更改PID命名空间,nsenter将分叉,以便新程序及其子程序共享相同的PID命名空间,并且彼此可见。如果使用--no-fork,那么新程序将被执行,而不需要分叉。
(手册在那里有些混乱;我已经清除了上面引用的部分和的下一个版本util-linux将包括一个修复程序。)
输入PID命名空间不会将当前进程移动到该命名空间,它只会导致在该命名空间中创建新的子进程。因此,当前进程(调用setns的进程)在新的命名空间中对其子进程不可见。为了避免这种情况,nsenter进入新的名称空间,然后分叉,这将在新名称空间中生成一个新的nsenter,然后调用exec;因此,exec‘’ed程序位于新的命名空间中。
还请参阅man setns中PID名称空间的说明:
如果fd引用PID命名空间,则语义与其他命名空间类型有些不同:将调用线程与PID命名空间重新组合只会更改随后创建调用方子进程的PID命名空间;它不会更改调用方本身的PID命名空间。
您将在/proc名称空间条目中看到这一点:/proc/.../ns有两个PID条目,一个是pid (进程的名称空间),另一个是pid_for_children (用于新子类的名称空间)。
(exec本身不会创建新进程。)
https://unix.stackexchange.com/questions/581941
复制相似问题