linux:kernel:namespace:the_namespaces_api

差分

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

この比較画面へのリンク

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
linux:kernel:namespace:the_namespaces_api [2013/07/23 12:58] – [既に存在する名前空間に参加する: setns()] tenforwardlinux:kernel:namespace:the_namespaces_api [2016/07/12 18:23] (現在) – [名前空間の操作,その 2: 名前空間 API] tenforward
行 3: 行 3:
 名前空間はグローバルなシステムリソースを抽象的なものの中に包みこむ.隔離されたリソースのインスタンスを持つ名前空間内にプロセスを出現させるということである.名前空間は様々な目的に使われる.最も有名なのは軽量の仮想化テクニックであるコンテナの実装である.これは名前空間と名前空間 API の詳細を見ていく記事のシリーズの第 2 部である.この記事では名前空間 API を少し詳細に見ていく.そして多数のサンプルプログラムで実際の API を説明する. 名前空間はグローバルなシステムリソースを抽象的なものの中に包みこむ.隔離されたリソースのインスタンスを持つ名前空間内にプロセスを出現させるということである.名前空間は様々な目的に使われる.最も有名なのは軽量の仮想化テクニックであるコンテナの実装である.これは名前空間と名前空間 API の詳細を見ていく記事のシリーズの第 2 部である.この記事では名前空間 API を少し詳細に見ていく.そして多数のサンプルプログラムで実際の API を説明する.
  
-名前空間の API は 3 つのシステムコール,clone(), unshare(), setns() と多数の /proc 以下のファイルから構成される.この記事では,この全てのシステムコールと /proc 以下のファイルをいくつか見ていく.操作するのがどのタイプの名前空間なのかを特定するために,3 つのシステムコールは CLONE_NEW* という定数を仕様する.先の記事で挙られていた CLONE_NEWIPC, CLONE_NEWNS, CLONE_NEWNET, CLONE_NEWPID, CLONE_NEWUSER, CLONE_NEWUTS である.+名前空間の API は 3 つのシステムコール,clone(), unshare(), setns() と多数の /proc 以下のファイルから構成される.この記事では,この全てのシステムコールと /proc 以下のファイルをいくつか見ていく.操作するのがどのタイプの名前空間なのかを特定するために,3 つのシステムコールは CLONE_NEW* という定数を使用する.先の記事で挙られていた CLONE_NEWIPC, CLONE_NEWNS, CLONE_NEWNET, CLONE_NEWPID, CLONE_NEWUSER, CLONE_NEWUTS である.
  
 ===== 新しい名前空間内で子プロセスを生成する: clone() ===== ===== 新しい名前空間内で子プロセスを生成する: clone() =====
行 154: 行 154:
 以前までのバージョンのカーネルでは,setns() を使って mount, PID, ユーザ名前空間に参加する事はできなかった.しかし 3.8 以降で,全ての名前空間に参加が可能になった. 以前までのバージョンのカーネルでは,setns() を使って mount, PID, ユーザ名前空間に参加する事はできなかった.しかし 3.8 以降で,全ての名前空間に参加が可能になった.
  
-===== 名前空間から抜ける: unsahre() =====+===== 名前空間から抜ける: unshare() =====
  
 名前空間 API の最後のシステムコールは unshare() である. 名前空間 API の最後のシステムコールは unshare() である.
行 163: 行 163:
  
 unshare() システムコールは clone() と同様の機能を提供する.しかし,呼び出したプロセス上での操作となる.つまり,CLONE_NEW* ビットを引数として取り新しい名前空間を作成し,呼び出し元を名前空間のメンバーにする (clone() と同様に,我々がここでは扱わない名前空間の操作以外の機能を提供する).unshare() の主な目的は,(clone() が行うような) 新しいプロセスやスレッドを作る必要なしに名前空間 (や他) の副次的な効果を隔離することである. unshare() システムコールは clone() と同様の機能を提供する.しかし,呼び出したプロセス上での操作となる.つまり,CLONE_NEW* ビットを引数として取り新しい名前空間を作成し,呼び出し元を名前空間のメンバーにする (clone() と同様に,我々がここでは扱わない名前空間の操作以外の機能を提供する).unshare() の主な目的は,(clone() が行うような) 新しいプロセスやスレッドを作る必要なしに名前空間 (や他) の副次的な効果を隔離することである.
 +
 +clone() システムコールの他の効果はひとまず置いといて,
 +
 +<code c>clone(..., CLONE_NEWXXX, ....);</code>
 +
 +という形式での呼び出しと,名前空間という点で,大体同じとなるのは以下のようなものである.
 +
 +<code c>
 +    if (fork() == 0)
 +        unshare(CLONE_NEWXXX);      /* Executed in the child process */
 +</code>
 +
 +unshare() システムコールの使い方の一つは,unshare コマンドの実装にある.このコマンドは,シェルとは別の名前空間内でコマンドを実行できるというものである.おおまかなコマンドの実行方法は
 +
 +<code>
 +    unshare [options] program [arguments]
 +</code>
 +
 +options は arguments を引数として program を実行する前に unshare する名前空間を指定するコマンドラインのオプションである.
 +
 +unshare コマンドの実装のキーとなる部分はわかりやすい.
 +
 +<code c>
 +     /* Code to initialize 'flags' according to command-line options
 +        omitted */
 +
 +     unshare(flags);
 +
 +     /* Now execute 'program' with 'arguments'; 'optind' is the index
 +        of the next command-line argument after options */
 +
 +     execvp(argv[optind], &argv[optind]);
 +</code>
 +
 +unshare コマンドのシンプルな実装 (unshare.c) は [[http://lwn.net/Articles/531826/|以下]] である.
 +
 +以下のシェルのセッションでは,unshare.c を使い,別のマウント名前空間でシェルを実行している.先週の記事で注意したようにマウント名前空間は,プロセスのグループから見えるファイルシステムのマウントポイントの組を隔離するものであり,異なるマウント名前空間内のプロセスは異なったファイルシステム構造が持てるというものである.
 +
 +<code>
 +    # echo $$                             # シェルの PID を見る
 +    8490
 +    # cat /proc/8490/mounts | grep mq     # 名前空間内のマウントを一つ見る
 +    mqueue /dev/mqueue mqueue rw,seclabel,relatime 0 0
 +    # readlink /proc/8490/ns/mnt          # マウント名前空間の ID を見る
 +    mnt:[4026531840]
 +    # ./unshare -m /bin/bash              # 別のマウント名前空間で新しいシェルを実行
 +    # readlink /proc/$$/ns/mnt            # マウント名前空間の ID を見る
 +    mnt:[4026532325]
 +</code>
 +
 +2 度実行した readlink コマンドの出力を比べると,2 つのシェルは別のマウント名前空間にいることが示されている.片方の名前空間のマウントポイントの組を変化させ,他の名前空間で変化が見えるかどうかをチェックすることで,2 つのプログラムが別の名前空間内にいることを別の方法でデモする.
 +
 +<code>
 +    # umount /dev/mqueue                  # シェルからマウントポイントを削除
 +    # cat /proc/$$/mounts | grep mq       # マウントポイントが存在しないことを確認
 +    # cat /proc/8490/mounts | grep mq     # 他の名前空間ではまだ存在したままかどうか?
 +    mqueue /dev/mqueue mqueue rw,seclabel,relatime 0 0
 +</code>
 +
 +最後の 2 つのコマンドの出力から分かるように,/dev/mqueue マウントポイントは片方のマウント名前空間では見えなくなるが,別の名前空間では存在したままである.
 +
 +===== 最後に =====
 +
 +この記事では,名前空間API の基本的な部分を見て,それをどのように組み合わせて使うかを示した.後に続く記事では,他のいくつかの名前空間でより深い部分を見ていく.特に PID とユーザ名前空間を見る.ユーザ名前空間は,アプリケーションが,従来は特権アプリに限られていたカーネルインターフェースの使用するための新しい可能性を広げるものである.
  
  • linux/kernel/namespace/the_namespaces_api.1374584283.txt.gz
  • 最終更新: 2013/07/23 12:58
  • by tenforward