文書の過去の版を表示しています。
名前空間の操作,その 2: 名前空間 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 である.
新しい名前空間内で子プロセスを生成する: clone()
名前空間を作成する方法の 1 つが,新しいプロセスを生成するシステムコールである clone() を使うことによるものである.clone() は以下のようなプロトタイプを持つ.
int clone(int (*child_func)(void *), void *child_stack, int flags, void *arg);
基本的にclone() は,伝統的な UNIX の fork() システムコールのより一般的なバージョジョンである.その機能は flags により制御される.clone() の様々な操作をコントロールするための,全部で 20 以上の異なる CLONE_* フラグが存在する.そのフラグは仮想メモリやオープンするファイルディスクリプタやシグナル操作のようなリソースを親子で共有するかどうかのためのものを含む.呼び出しで CLONE_NEW* の一つが指定された場合,指定したタイプに一致する新しい名前空間が作成され,新しいプロセスがその名前空間のメンバーとして作成される.flags には複数の CLONE_NEW* ビットを指定することも可能である.
我々のサンプルプログラム (demo_uts_namespace.c) は UTS 名前空間を作るために CLONE_NEWUTS を指定して clone() を使っている.先週見たように,UTS 名前空間は 2 つのシステムの識別子であるホスト名と NIS ドメイン名を隔離する.これは sethostname() と setdomainname() を使って設定され,uname() システムコールを使って返される.全ソースコードはここにある.以下で,このプログラムのキーとなるいくつかの部分にフォーカスを当てる (簡潔な記述のために,サンプルの全コードには載っているエラーチェックを省いている).
サンプルプログラムはコマンドラインオプションを 1 つ与える.実行すると,新しい UTS 名前空間で動く子プロセスを 1 つ作成する.名前空間内で,子プロセスはコマンドラインオプションで与えた文字列でホスト名を変更する.
メインプログラムの最初の重要な部分は子プロセスを作成する clone() コールである:
child_pid = clone(childFunc, child_stack + STACK_SIZE, /* Points to start of downwardly growing stack */ CLONE_NEWUTS | SIGCHLD, argv[1]); printf("PID of child created by clone() is %ld\n", (long) child_pid);