名前


fork - 子プロセスを生成する

書式


#include <sys/types.h> #include <unistd.h>

pid_t fork(void);

説明


fork() は呼び出し元プロセスを複製して新しいプロセスを生成する。 child で参照される新しいプロセスは、以下の点を除き、 parent で参照される呼び出し元プロセスの完全な複製である:
* 子プロセスは自身の独自のプロセス ID を持ち、 この PID は既存のどのプロセスグループ (setpgid(2)) の ID とも一致しない。
* 子プロセスの親プロセス ID は、親プロセスのプロセス ID と同じである。
* 子プロセスは親プロセスのメモリロック (mlock(2), mlockall(2)) を引き継がない。
* プロセスの資源利用量 (getrusage(2)) と CPU タイムカウンタ (times(2)) が、子プロセスでは 0 にリセットされる。
* 子プロセスの処理待ちのシグナルの集合 (sigpending(2)) は、初期状態では空になる。
* 子プロセスは親プロセスからセマフォ調整 (semop(2)) を引き継がない。
* 子プロセスは親プロセスからレコードロック (fcntl(2)) を引き継がない。
* 子プロセスは親プロセスからタイマー (setitimer(2) alarm(3), timer_create(3)) を引き継がない。
* 子プロセスは親プロセスから主だった非同期 I/O 操作 (aio_read(3), aio_write(3)) を引き継がない。
上記のリストにあるプロセス属性は、POSIX.1-2001 で全て指定されている。 親プロセスと子プロセスは、以下の Linux 固有のプロセス属性も異なる:
* 子プロセスは親プロセスからディレクトリ変更通知 (dnotify) (fcntl(2) における F_NOTIFY の説明を参照) を引き継がない。
* prctl(2)PR_SET_PDEATHSIG の設定がリセットされ、子プロセスは親プロセスが終了したときに シグナルを受信しない。
* madvise(2)MADV_DONTFORK フラグでマークされたメモリマッピングは、 fork(2) によって引き継がれない。
* 子プロセスの終了シグナルは常に SIGCHLD である (clone(2) を参照)。
さらに以下の点について注意すること:
* 子プロセスはシングルスレッド — fork(2) を呼び出したスレッドで生成される。 親プロセスの仮想アドレス空間全体が子プロセスに複製される。 これにはミューテックス (mutex) の状態・条件変数・ pthread オブジェクトが含まれる。 これが引き起こす問題を扱うには、 pthread_atfork(3) を使うと良いだろう。
* 子プロセスは親プロセスが持つ オープンファイルディスクリプタの集合のコピーを引き継ぐ。 子プロセスの各ファイルディスクリプタは、 親プロセスのファイルディスクリプタに対応する 同じオープンファイルディスクリプタを参照する (open(2) を参照)。 これは 2 つのディスクリプタが、ファイル状態フラグ・ 現在のファイルオフセット・シグナル駆動 (signal-driven) I/O 属性 (fcntl(2) における F_SETOWN, F_SETSIG の説明を参照) を共有することを意味する。
* 子プロセスは親プロセスが持つオープンメッセージキューディスクリプタ (mq_overview(7) を参照) の集合のコピーを引き継ぐ。 子プロセスの各ディスクリプタは、 親プロセスのディスクリプタに対応する 同じオープンメッセージキューディスクリプタを参照する。 これは 2 つのディスクリプタが同じフラグ (mq_flags) を共有することを意味する。

返り値


成功した場合、親の実行スレッドには子プロセスの PID が返され、 子の実行スレッドには 0 が返される。 失敗した場合、親プロセスに -1 を返し、子プロセスは生成されない。 また、 errno が適切に設定される。

エラー


EAGAIN
 親プロセスのページ・テーブルのコピーと 子プロセスのタスク構造に生成に必要なメモリを fork() が割り当てることができなかった。
EAGAIN
 呼び出し元の RLIMIT_NPROC 資源の制限 (resource limit) に達したために、新しいプロセスを生成できなかった。 この制限を超えるには、プロセスは CAP_SYS_ADMIN または CAP_SYS_RESOURCE ケーパビリティ (capability) を持たなくてはならない。
ENOMEM
 メモリが足りないために、 fork() は必要なカーネル構造体を割り当てることができなかった。

準拠


SVr4, 4.3BSD, POSIX.1-2001.

注意


Linux では、 fork() を 書き込み時コピー (copy-on-write)・ページを用いて実装している。 したがって、fork を行うことの唯一のデメリットは、 親プロセスのページ・テーブルを複製と 子プロセス自身のタスク構造の作成のための時間とメモリが必要なことである。


pipe(2) および wait(2) を参照。

関連項目


clone(2), execve(2), setrlimit(2), unshare(2), vfork(2), wait(2), capabilities(7)

openSUSE Logo

コンテンツ