web-dev-qa-db-ja.com

子が新しく入力されたPID名前空間にも存在することを保証するために、 `nsenter`が` exec`の前に `fork`を呼び出す必要があるのはなぜですか?

nsenterのサブプロセスとして実行されるbashは、setnsシステムコールを使用して既存の名前空間に参加し、execを使用して指定されたプログラムを実行すると想定しています。

しかし、nsentersetnsの前に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.
4
Shuzheng

説明は man nsenter の「PID名前空間」セクションに記載されています。

子には、nsenterプロセスとは別にマッピングを処理するための一連のPIDがあります。 nsenterは、PID名前空間を変更する場合、デフォルトでforkするため、新しいプログラムとその子は同じPID名前空間を共有し、お互いに表示されます。 --no-forkを使用すると、新しいプログラムはフォークせずに実行されます。

(マニュアルは少し混乱しています。上記の引用セクションをクリーンアップしました util-linuxの次のリリースには修正が含まれます 。)

PID名前空間を入力しても、現在のプロセスはその名前空間に移動されません。その名前空間に新しい子が作成されるだけです。その結果、現在のプロセス(setnsを呼び出すプロセス)は、新しい名前空間の子には見えません。これを回避するには、nsenterが新しいネームスペースに入り、次にフォークして、新しいネームスペースに新しいnsenterが生成され、execが呼び出されます。その結果、実行されたプログラムは新しい名前空間にあります。

man setns のPID名前空間の説明も参照してください。

fdがPID名前空間を参照する場合、セマンティクスは他の名前空間タイプとは多少異なります。呼び出しスレッドをPID名前空間に再度関連付けると、変更されるPID名前空間のみが変更されますその後作成された呼び出し元の子プロセスが配置されます。呼び出し元自体のPID名前空間は変更されません。

これは/proc名前空間エントリで実際に動作します。/proc/.../nsにはpid(プロセスの名前空間)とpid_for_children(新しい子供たち)。

exec自体は新しいプロセスを作成しません。)

7
Stephen Kitt