Linux

為什麼 nsenter 需要在 exec 之前呼叫 fork 以確保任何孩子也將在新進入的 PID 命名空間中?

  • April 27, 2020

我假設nsenter作為 的子程序執行的bash,利用setns系統呼叫加入現有的命名空間,然後使用 執行指定的程序exec

但是,如果在 ‘ing之前nsenter已經呼叫過,為什麼需要係統呼叫來確保子程序也將在輸入的命名空間中?setns``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.

解釋在“PID 命名空間”部分給出man nsenter

子程序將有一組 PID 來處理與程序分開的映射nsenternsenter如果更改 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它本身不會創建新程序。)

引用自:https://unix.stackexchange.com/questions/581941