CLONE(2) | Linux Programmer's Manual | CLONE(2) |
名前
clone, __clone2 -子プロセスを作成する書式
/* Prototype for the glibc wrapper function */
#include <sched.h>
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
/* Prototype for the raw system call */
long clone(unsigned long flags, void *child_stack,
void *ptid, void *ctid,
struct pt_regs *regs);
Feature Test Macro Requirements for glibc wrapper function (see feature_test_macros(7)):
clone():
- Since glibc 2.14:
- _GNU_SOURCE
- Before glibc 2.14:
-
_BSD_SOURCE || _SVID_SOURCE
/* _GNU_SOURCE also suffices */
説明
clone() creates a new process, in a manner similar to fork(2).- CLONE_CHILD_CLEARTID (Linux 2.5.49 以降)
- 子プロセスが終了したときに子プロセスのメモリ内の ctid が指す場所にある子プロセスのスレッド ID を消去し、そのアドレスで futex を wake (起床) させる。このアドレスは set_tid_address(2) システムコールで変更することができる。この機能はスレッドライブラリで使用される。
- CLONE_CHILD_SETTID (Linux 2.5.49 以降)
- 子プロセスのメモリ内の ctid が指す場所に子プロセスのスレッド ID を格納する。
- CLONE_FILES (Linux 2.0 以降)
-
CLONE_FILES が設定された場合、呼び出し元のプロセスと子プロセスはファイルディスクリプタのテーブルを共有する。呼び出し元プロセスとその子プロセスの一方が作成したファイルディスクリプタは、もう一方においても有効である。同じように、一方のプロセスがファイルディスクリプタを閉じたり、 (
fcntl(2)
F_SETFD 操作を使って) ディスクリプタに関連するフラグを変更したりすると、もう一方のプロセスにも影響する。
- CLONE_FS (Linux 2.0 以降)
-
CLONE_FS が設定された場合、呼び出し元のプロセスと子プロセスが同じファイル・システム情報を共有する。ファイル・システム情報は、ファイル・システムのルート (root)、カレント・ワーキング・ディレクトリ (current working directory) や umask などである。呼び出し元のプロセスや子プロセスのどちらか一方によって
chroot(2),
chdir(2),
umask(2) が呼び出されると、もう一方のプロセスにも影響が及ぶ。
- CLONE_IO (Linux 2.6.25 以降)
-
CLONE_IO が設定された場合、新しいプロセスは呼び出し元のプロセスと I/O コンテキストを共有する。このフラグが設定されていない場合には、 (
fork(2) の場合と同様) 新しいプロセスは自分専用の I/O コンテキストを持つ。
- CLONE_NEWIPC (Linux 2.6.19 以降)
-
CLONE_NEWIPC が設定された場合、新しい IPC 名前空間 (namespace) でプロセスを作成する。このフラグが設定されていない場合、 (
fork(2) の場合と同様) 呼び出し元のプロセスと同じ IPC 名前空間でプロセスが作成される。このフラグは、コンテナの実装での使用を意図して用意されたものである。
- CLONE_NEWNET (Linux 2.6.24 以降)
-
(このフラグの実装は、Linux 2.6.29 あたりまでには完成した。)
- CLONE_NEWNS (Linux 2.4.19 以降)
-
子プロセスを新しいマウント名前空間 (mount namespace) で開始する。
- CLONE_NEWPID (Linux 2.6.24 以降)
-
CLONE_NEWPID が設定された場合、新しい PID 名前空間でプロセスを作成する。このフラグが設定されていない場合、 (
fork(2) の場合と同様) 呼び出し元のプロセスと同じ PID 名前空間でプロセスが作成される。このフラグは、コンテナの実装での使用を意図して用意されたものである。
- CLONE_NEWUTS (Linux 2.6.19 以降)
-
CLONE_NEWUTS が設定された場合、新しい UTS 名前空間でプロセスを作成する。新しい UTS 名前空間の識別子の初期値は、呼び出し元のプロセスの UTS 名前空間の識別子を複製したものとなる。このフラグが設定されていない場合、 (
fork(2) の場合と同様) 呼び出し元のプロセスと同じ UTS 名前空間でプロセスが作成される。このフラグは、コンテナの実装での使用を意図して用意されたものである。
- CLONE_PARENT (Linux 2.3.12 以降)
-
CLONE_PARENT が設定された場合、新しい子供の (
getppid(2) で返される) 親プロセスは呼び出し元のプロセスの親プロセスと同じになる。
- CLONE_PARENT_SETTID (Linux 2.5.49 以降)
- 親プロセスと子プロセスのメモリ内の ptid が指す領域に子プロセスのスレッド ID を格納する。 (Linux 2.5.32-2.5.48 では、同じことをする CLONE_SETTID というフラグが存在した。)
- CLONE_PID (廃止予定)
- CLONE_PID が設定された場合、子プロセスは呼び出し元のプロセスと同じプロセス ID で作成される。これはシステムをハッキングするのには便利だが、それ以外にはあまり使われない。 Linux 2.3.21 以降では、システムのブートプロセス (PID 0) だけがこのフラグを指定できる。 Linux 2.5.16 で削除された。
- CLONE_PTRACE (Linux 2.2 以降)
- CLONE_PTRACE が指定され、かつ呼び出し元のプロセスが追跡 (trace) されていた場合、子プロセスも同様に追跡される。 ( ptrace(2) を参照のこと)
- CLONE_SETTLS (Linux 2.5.32 以降)
- newtls 引き数は、新しい TLS (Thread Local Storage) ディスクリプタである。 ( set_thread_area(2) を参照のこと)
- CLONE_SIGHAND (Linux 2.0 以降)
-
CLONE_SIGHAND が設定された場合、呼び出し元のプロセスと子プロセスは同じシグナル・ハンドラのテーブルを共有する。呼び出し元のプロセスまたは子プロセスのどちらかが
sigaction(2) を呼び出してシグナルに対応する動作を変更した場合、もう一方のプロセスのシグナル動作も変更される。但し、呼び出し元のプロセスと子プロセスは、プロセス毎に、シグナル・マスク (signal mask) と処理待ちシグナルの集合を持っている。このため、あるプロセスは、
sigprocmask(2) を使用して、もう一方のプロセスに影響を与えずにシグナルを禁止 (block) したり許可 (unblock) したりできる。
- CLONE_STOPPED (Linux 2.6.0-test2 以降)
-
CLONE_STOPPED が設定されると、子プロセスは最初 (
SIGSTOP シグナルを送られたかのように) 停止した状態となる。子プロセスを再開させるには
SIGCONT シグナルを送信しなければならない。
- CLONE_SYSVSEM (Linux 2.5.10 以降)
- CLONE_SYSVSEM がセットされると、子プロセスと呼び出し元プロセスは一つの System V セマフォのアンドゥ値リスト ( semop(2) 参照) を共有する。このフラグがセットされていなければ、子プロセスは独自のアンドゥリストを持つ (リストの初期値は空である)。
- CLONE_THREAD (Linux 2.4.0-test8以降)
-
CLONE_THREAD が設定された場合、子プロセスは呼び出し元のプロセスと同じスレッド・グループに置かれる。
CLONE_THREAD についての以降の議論を読みやすくするため、「スレッド」という用語はスレッド・グループの中のプロセスを参照するのに使うこととする。
- CLONE_UNTRACED (Linux 2.5.46 以降)
- CLONE_UNTRACED が指定されると、 trace を行っているプロセスはこの子プロセスに CLONE_PTRACE を適用することができない。
- CLONE_VFORK (Linux 2.2 以降)
-
CLONE_VFORK が設定された場合、 (
vfork(2) と同様に) 子プロセスが
execve(2) または
_exit(2) によって仮想メモリを解放するまで、呼び出し元のプロセスの実行は停止される。
- CLONE_VM (Linux 2.0 以降)
-
CLONE_VM が設定された場合、呼び出し元のプロセスと子プロセスは同じメモリ空間で実行される。特に、呼び出し元のプロセスや子プロセスの一方がメモリに書き込んだ内容はもう一方のプロセスからも見ることができる。さらに、子プロセスや呼び出し元のプロセスの一方が
mmap(2) や
munmap(2) を使ってメモリをマップしたりアンマップした場合、もう一方のプロセスにも影響が及ぶ。
生のシステムコールのインターフェース
The raw clone() system call corresponds more closely to fork(2) in that execution in the child continues from the point of the call. As such, the fn and arg arguments of the clone() wrapper function are omitted. Furthermore, the argument order changes. The raw system call interface on x86 and many other architectures is roughly:
long clone(unsigned long flags, void *child_stack,
void *ptid, void *ctid,
struct pt_regs *regs);
生のシステムコールのもう一つの違いは、 child_stack 引き数がゼロでも良いことである。この場合には、どちらかのプロセスがスタックを変更した時に、書き込み時コピー (copy-on-write) 方式により子プロセスがスタック・ページの独立したコピーを得られることが保証される。この場合、正常に動作させるためには、 CLONE_VM オプションを指定してはならない。
For some architectures, the order of the arguments for the system call differs from that shown above. On the score, microblaze, ARM, ARM 64, PA-RISC, arc, Power PC, xtensa, and MIPS architectures, the order of the fourth and fifth arguments is reversed. On the cris and s390 architectures, the order of the first and second arguments is reversed.
blackfin, m68k, and sparc
The argument-passing conventions on blackfin, m68k, and sparc are different from descriptions above. For details, see the kernel (and glibc) source.ia64
ia64 では、別のインターフェースが使用される:
int __clone2(int (*fn)(void *),
void *child_stack_base, size_t stack_size,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
The prototype shown above is for the glibc wrapper function; the raw system call interface has no fn or arg argument, and changes the order of the arguments so that flags is the first argument, and tls is the last argument.
__clone2() は clone() と同じように動作するが、以下の点が異なる: child_stack_base は子プロセスのスタックエリアの最小のアドレスを指し、 stack_size は child_stack_base が指し示すスタックエリアの大きさを示す。
Linux 2.4 and earlier
Linux 2.4 以前では、 clone() は引き数 ptid, tls, ctid を取らない。返り値
成功した場合、呼び出し元の実行スレッドには子プロセスのスレッドID が返される。失敗した場合、呼び出し元のコンテキストには-1 が返され、子プロセスは作成されず、 errno が適切に設定される。エラー
- EAGAIN
- すでに実行中のプロセスが多すぎる。
- EINVAL
- CLONE_SIGHAND が指定されていたが、 CLONE_VM が指定されていなかった。 (Linux 2.6.0-test6 以降)
- EINVAL
- CLONE_THREAD が指定されていたが、 CLONE_SIGHAND が指定されていなかった。 (Linux 2.5.35 以降)
- EINVAL
- CLONE_FS と CLONE_NEWNS の両方が flags に指定された。
- EINVAL
- CLONE_NEWIPC と CLONE_SYSVSEM の両方が flags に指定された。
- EINVAL
- CLONE_NEWPID と CLONE_THREAD の両方が flags に指定された。
- EINVAL
- child_stack にゼロを指定した場合に clone() が返す。
- EINVAL
- flags に CLONE_NEWIPC が指定されたが、カーネルでオプション CONFIG_SYSVIPC と CONFIG_IPC_NS が有効になっていなかった。
- EINVAL
- flags に CLONE_NEWNET が指定されたが、カーネルでオプション CONFIG_NET_NS が有効になっていなかった。
- EINVAL
- flags に CLONE_NEWPID が指定されたが、カーネルでオプション CONFIG_PID_NS が有効になっていなかった。
- EINVAL
- flags に CLONE_NEWUTS が指定されたが、カーネルでオプション CONFIG_UTS が有効になっていなかった。
- ENOMEM
- 子プロセスのために確保すべきタスク構造体や、呼び出し元のコンテキストの一部をコピーするのに必要なメモリを十分に割り当てることができない。
- EPERM
- 非特権プロセス ( CAP_SYS_ADMIN を持たないプロセス) が CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS を指定した。
- EPERM
- PID が 0 以外のプロセスによって CLONE_PID が指定された。
バージョン
libc5 には clone() はない。glibc2 では clone() が提供されており、このマニュアルページに記載の通りである。準拠
clone() は Linux 特有であり、移植を考慮したプログラムでは使用すべきではない。注意
カーネル 2.4.x 系列では、一般的には CLONE_THREAD フラグを指定しても新しいスレッドの親を呼び出し元プロセスの親と同じにはしない。しかし、バージョン 2.4.7〜2.4.18 のカーネルでは、 (カーネル 2.6 と同じように) CLONE_THREAD フラグを指定すると、暗黙のうちに CLONE_PARENT フラグを指定したことになる。バグ
NPTL スレッド・ライブラリを含んでいる GNU C ライブラリのいくつかのバージョンには、 getpid(2) のラッパー関数が含まれており、このラッパー関数は PID をキャッシュする。このキャッシュ処理が正しく動作するためには glibc の clone() のラッパー関数での助けが必要だが、現状の実装では、ある状況下においてキャッシュが最新とならない可能性がある。特に、 clone() の呼び出し直後にシグナルが子プロセスに配送された場合に、そのシグナルに対するハンドラ内で getpid(2) を呼び出すと、それまでに clone のラッパー関数が子プロセスの PID キャッシュを更新する機会が得られていなければ、呼び出し元プロセス ("親プロセス") の PID が返される可能性がある。 (この議論では、子プロセスが CLONE_THREAD を使って作成された場合のことは無視している。子プロセスが CLONE_THREAD を作って作成された場合には、呼び出し元と子プロセスは同じスレッド・グループに属すので、 getpid(2) は子プロセスと clone() を呼び出したプロセスで同じ値を返すのが「正しい」。キャッシュが最新とならない問題 (stale-cache problem) は、 flags に CLONE_VM が含まれている場合にも発生しない。) 本当の値を得るためには、次のようなコードを使う必要があるかもしれない。
#include <syscall.h>
pid_t mypid;
mypid = syscall(SYS_getpid);
EXAMPLE
Create a child that executes in a separate UTS namespace
The following program demonstrates the use of clone() to create a child process that executes in a separate UTS namespace. The child changes the hostname in its UTS namespace. Both parent and child then display the system hostname, making it possible to see that the hostname differs in the UTS namespaces of the parent and child. For an example of the use of this program, see setns(2).#define _GNU_SOURCE
#include <sys/wait.h>
#include <sys/utsname.h>
#include <sched.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE);\
} while (0)
static int /* Start function for cloned child */
childFunc(void *arg)
{
struct utsname uts;
/* Change hostname in UTS namespace of child */
if (sethostname(arg, strlen(arg)) == -1)
errExit("sethostname");
/* Retrieve and display hostname */
if (uname(&uts) == -1)
errExit("uname");
printf("uts.nodename in child: %s\n", uts.nodename);
/* Keep the namespace open for a while, by sleeping.
This allows some experimentation--for example, another
process might join the namespace. */
sleep(200);
return 0; /* Child terminates now */
}
#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */
int
main(int argc, char *argv[])
{
char *stack; /* Start of stack buffer */
char *stackTop; /* End of stack buffer */
pid_t pid;
struct utsname uts;
if (argc < 2) {
fprintf(stderr, "Usage: %s <child-hostname>\n", argv[0]);
exit(EXIT_SUCCESS);
}
/* Allocate stack for child */
stack = malloc(STACK_SIZE);
if (stack == NULL)
errExit("malloc");
stackTop = stack + STACK_SIZE; /* Assume stack grows downward */
/* Create child that has its own UTS namespace;
child commences execution in childFunc() */
pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]);
if (pid == -1)
errExit("clone");
printf("clone() returned %ld\n", (long) pid);
/* Parent falls through to here */
sleep(1); /* Give child time to change its hostname */
/* Display hostname in parent's UTS namespace. This will be
different from hostname in child's UTS namespace. */
if (uname(&uts) == -1)
errExit("uname");
printf("uts.nodename in parent: %s\n", uts.nodename);
if (waitpid(pid, NULL, 0) == -1) /* Wait for child */
errExit("waitpid");
printf("child has terminated\n");
exit(EXIT_SUCCESS);
}
関連項目
fork(2), futex(2), getpid(2), gettid(2), kcmp(2), set_thread_area(2), set_tid_address(2), setns(2), tkill(2), unshare(2), wait(2), capabilities(7), pthreads(7)この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.51 の一部である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2013-04-16 | Linux |