linux:kernel:namespace:more_on_pid_namespaces

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
linux:kernel:namespace:more_on_pid_namespaces [2013/08/24 14:10] – [procfs ファイルシステムのマウント (再考)] tenforwardlinux:kernel:namespace:more_on_pid_namespaces [2013/08/27 15:12] (現在) tenforward
行 1: 行 1:
-====== PID 名前空間について更にもう少し ======+====== 名前空間の操作,その 4: PID 名前空間について更にもう少し ======
 この記事では,PID 名前空間の先週の議論を続ける (そして名前空間に関する進行中のシリーズを続ける).PID 名前空間の利用法の一つは,パッケージ化したプロセス (コンテナ) を実装することである.これは独立した Linux システムのように振る舞う.伝統的なシステムのキーとなる部分は init プロセスである.そしてこれは PID 名前空間を使ったコンテナでも同様である.なので,init プロセスの特別な役割を調べ,伝統的な init プロセスとは違う点について 1 つ,2 つ述べる.加えて,PID 名前空間に適用する時の名前空間 API の他の詳細を調べる. この記事では,PID 名前空間の先週の議論を続ける (そして名前空間に関する進行中のシリーズを続ける).PID 名前空間の利用法の一つは,パッケージ化したプロセス (コンテナ) を実装することである.これは独立した Linux システムのように振る舞う.伝統的なシステムのキーとなる部分は init プロセスである.そしてこれは PID 名前空間を使ったコンテナでも同様である.なので,init プロセスの特別な役割を調べ,伝統的な init プロセスとは違う点について 1 つ,2 つ述べる.加えて,PID 名前空間に適用する時の名前空間 API の他の詳細を調べる.
  
行 100: 行 100:
 </code> </code>
  
 +引数 fd は呼び出し元の PID 名前空間の子孫である PID 名前空間を指すファイルディスクリプタである.ファイルディスクリプタは目的の名前空間内のプロセスの一つに対する /proc/PID/ns/pid ファイルを open することで取得する.unshare() と同様に,setns() は呼び出し元を PID 名前空間に移動しない.代わりに,その後に呼び出し元が作成する子プロセスが,その名前空間内に入る.
 +
 +このシリーズの 2 つ目の記事で紹介した [[http://lwn.net/Articles/532748/|ns_exec.c]] プログラムの改良版を使って,行おうとすることを理解するまでは驚きに思える PID 名前空間で setns() を使う際のいくつかの側面をデモしてみよう.新しいプログラム [[http://lwn.net/Articles/533495/|ns_run.c]] は以下のように使う.
 +
 +<code>
 +    ns_run [-f] [-n /proc/PID/ns/FILE]... command [arguments]
 +</code>
 +
 +このプログラムは -n オプションで指定した /proc/PID/ns ファイルで指定した名前空間に参加するために setns() を使用する.それから,オプションの arguments と共に指定した command を続けて実行する.-f オプションを指定した場合,コマンドを実行する子プロセスを作成するのに fork() を使用する.
 +
 +ターミナルウィンドウで,通常の実行方法で新しい PID 名前空間内で simple_init プログラムを実行したと仮定しよう.子プロセスを刈り取った時に分かるように冗長なログを取りながら.
 +
 +<code>
 +    # ./ns_child_exec -p ./simple_init -v
 +            init: my PID is 1
 +    init$ 
 +</code>
 +
 +そしてここで 2 つ目のターミナルウィンドウにスイッチし,ここで ns_run プログラムで orphan プログラムを実行する.これは simple_init が管理する PID 名前空間内で 2 つプロセスを作成することになる.
 +
 +<code>
 +    # ps -C sleep -C simple_init
 +      PID TTY          TIME CMD
 +     9147 pts/8    00:00:00 simple_init
 +     # ./ns_run -f -n /proc/9147/ns/pid ./orphan
 +     Parent (PID=2) created child with PID 3
 +     Parent (PID=2; PPID=0) terminating
 +     # 
 +     Child  (PID=3) now an orphan (parent PID=1)
 +     Child  (PID=3) terminating
 +</code>
 +
 +orphan プログラムが実行されたとき,作成された「親の」プロセス (PID 2) からの出力を見ると,親のプロセス ID が 0 であることが分かる.これは,orphan プロセスを開始させたプロセス (ns_run) が異なる名前空間,つまりその名前空間のメンバーが「親の」プロセスからは見えない事を示している.[[http://lwn.net/Articles/531419/#getppid_0|既に書いた記事のように]],この場合 getppid() は 0 を返す.
 +
 +以下の図は orphan の「親」プロセスが終了する前のプロセスの関係を示している.矢印はプロセス間の親子関係を示している.
 +
 +{{:linux:kernel:namespace:pidns_orphan_1.png|}}
 +
 +simple_init プログラムを実行したウィンドウに戻ると,以下のような出力が見える.
 +
 +<code>
 +    init: SIGCHLD handler: PID 3 terminated
 +</code>
 +
 +orphan によって作られた「子の」プロセス (PID 3) は simple_init によって刈り取られる.しかし,「親の」プロセス (PID 2) は刈り取られていない.これは「親の」プロセスは異なる名前空間の自身の親 (ns_run) が刈り取っているからである.以下の図は orphan の「親の」プロセスが終了し,「子」が終了する前のプロセスとその関係を示している.
 +
 +{{:linux:kernel:namespace:pidns_orphan_2.png|}}
 +
 +setns() と unshare() は PID 名前空間を特別に扱うと強調する価値はある.他のタイプの名前空間に対しては,これらのシステムコールは呼び出し元の名前空間を変更する.これらのシステムコールが呼び出し元の PID 名前空間を変更しない理由は,他の PID 名前空間のメンバーになることは,自身の PID のプロセスを変更させることにつながる.getpid() は,そのプロセスが属する PID 名前空間に関するプロセスの PID を報告するからである.多数のユーザ空間のプログラムやライブラリは (getpid() が報告する) プロセスの PID は一定であるという仮定がある (事実,GNU C ライブラリの getpid() のラッパー関数は PID を[[http://thread.gmane.org/gmane.linux.kernel/209103/focus=209130|キャッシュする]]).つまり,もしプロセスの PID が変化したら,これらのプログラムはうまく動かない.別の言い方をすると,プロセスの PID 名前空間のメンバーシップは,プロセスが作成された時に定義され,それ以降は変化できない (他のタイプの名前空間のメンバーシップとは異なる).
 +
 +===== 最後に =====
 +
 +この記事では,PID 名前空間の init の特別な役割を見て,ps などのツールが使えるようにするためにどのように PID 名前空間に対して procfs をマウントするかを示し,PID 名前空間を使う場合の unshare() と setns() の特殊性をいくつか見た.これで PID 名前空間についての話は完了した.次の記事では,ユーザネームスペースについて見ていく.
  • linux/kernel/namespace/more_on_pid_namespaces.1377353410.txt.gz
  • 最終更新: 2013/08/24 14:10
  • by tenforward