UNSHARE(2) | Linux Programmer's Manual | UNSHARE(2) |
unshare - プロセス実行コンテキストの一部を分離する
#include <sched.h> int unshare(int flags);
glibc
向けの機能検査マクロの要件
(feature_test_macros(7) 参照):
unshare():
unshare() を使うと、プロセスは他のプロセスと現在共有している 実行コンテキストの一部を分離することができる。 実行コンテキストの一部、たとえばマウント名前空間 (mount namespace) などは、新しいプロセスを fork(2) または vfork(2) を使って生成したときに、暗黙のうちに共有される。 一方、仮想メモリーなどは、 clone(2) を使ってプロセスを生成するときに、明示的に共有することを要求できる。
unshare() の主な利用法は、プロセスが新しいプロセスを生成することなく、 共有実行コンテキストを制御することである。
flags 引き数はビットマスクであり、 実行コンテキストのどの部分の共有を解除するかを表す。 この引き数は、以下の定数の 0 個以上の OR で指定する:
ユーザー名前空間の詳細は user_namespaces(7) を参照。
上記に加えて、 呼び出し元がシングルスレッドの場合 (すなわち別のプロセスやスレッドとアドレス空間を共有していない場合)、 CLONE_THREAD, CLONE_SIGHAND, CLONE_VM を指定することができる。 この場合、 これらのフラグは効果を持たない。 (CLONE_THREAD を指定すると自動的に CLONE_VM が指定されたとみなされ、 CLONE_VM を指定すると自動的に CLONE_SIGHAND が指定されたとみなされる点に注意してほしい。) プロセスがマルチスレッドの場合、 これらのフラグを使用するとエラーとなる。
flags に 0 が指定された場合、 unshare() は何も行わないので、 呼び出し元プロセスの実行コンテキストは、何も変更されない。
成功した場合は 0 が返される。 失敗した場合は -1 が返されて、 errno にはエラーを示す値が設定される。
unshare() システムコールは Linux カーネル 2.6.16 で追加された。
unshare() システムコールは Linux 固有である。
clone(2) で新しいプロセスを生成したときに共有される全てのプロセス属性を、 unshare() によって共有の解除ができるわけではない。 特に、カーネル 3.8 時点では、 unshare() に CLONE_SIGHAND, CLONE_THREAD, CLONE_VM の効果を取り消すためのフラグが実装されていない。 これらの機能は、必要であれば将来追加されるかもしれない。
以下のプログラムは
unshare(1)
コマンドの簡単な実装である。
このコマンドは、1
つ以上の名前空間の
unshare を行ってから、
コマンドライン引き数で指定されたコマンドを実行する。
以下はこのプログラムの使用例である。
新しいマウント名前空間でシェルを実行し、
元のシェルと新しいシェルが別のマウント名前空間にいることを確認している。
$ readlink /proc/$$/ns/mnt mnt:[4026531840] $ sudo ./unshare -m /bin/bash [sudo] password for cecilia: # readlink /proc/$$/ns/mnt mnt:[4026532325]
2 つの readlink(1) コマンドの出力が違うことから、 2 つのシェルは異なるマウント名前空間にいることが分かる。
/* unshare.c
A simple implementation of the unshare(1) command: unshare
namespaces and execute a command. */ #define _GNU_SOURCE #include <sched.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> /* A simple error-handling function: print an error message based
on the value in 'errno' and terminate the calling process */ #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0) static void usage(char *pname) {
fprintf(stderr, "Usage: %s [options] program [arg...]\n", pname);
fprintf(stderr, "Options can be:\n");
fprintf(stderr, " -i unshare IPC namespace\n");
fprintf(stderr, " -m unshare mount namespace\n");
fprintf(stderr, " -n unshare network namespace\n");
fprintf(stderr, " -p unshare PID namespace\n");
fprintf(stderr, " -u unshare UTS namespace\n");
fprintf(stderr, " -U unshare user namespace\n");
exit(EXIT_FAILURE); } int main(int argc, char *argv[]) {
int flags, opt;
flags = 0;
while ((opt = getopt(argc, argv, "imnpuU")) != -1) {
switch (opt) {
case 'i': flags |= CLONE_NEWIPC; break;
case 'm': flags |= CLONE_NEWNS; break;
case 'n': flags |= CLONE_NEWNET; break;
case 'p': flags |= CLONE_NEWPID; break;
case 'u': flags |= CLONE_NEWUTS; break;
case 'U': flags |= CLONE_NEWUSER; break;
default: usage(argv[0]);
}
}
if (optind >= argc)
usage(argv[0]);
if (unshare(flags) == -1)
errExit("unshare");
execvp(argv[optind], &argv[optind]);
errExit("execvp"); }
unshare(1), clone(2), fork(2), kcmp(2), setns(2), vfork(2), namespaces(7)
Linux カーネルソース内の Documentation/unshare.txt
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。
2014-09-21 | Linux |