書式
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
説明
fork()
は呼び出し元プロセスを複製して新しいプロセスを生成する。新しいプロセスは「子」プロセスと呼ばれ、呼び出し元プロセスは「親」プロセスと呼ばれる。
The child process and the parent process run in separate memory
spaces. At the time of fork() both memory spaces have the same
content. Memory writes, file mappings (mmap(2)), and unmappings
(munmap(2)) performed by one of the processes do not affect the
other.
The child process is an exact duplicate of the parent process
except for the following points:
上記のリストにあるプロセス属性は、POSIX.1
で全て指定されている。
親プロセスと子プロセスは、以下の
Linux
固有のプロセス属性も異なる:
- 子プロセスは親プロセスからディレクトリ変更通知
(dnotify) (fcntl(2) における
F_NOTIFY の説明を参照)
を引き継がない。
- prctl(2) の PR_SET_PDEATHSIG
の設定がリセットされ、子プロセスは親プロセスが終了したときに
シグナルを受信しない。
- timer slack value
のデフォルト値には、親プロセスの現在の
timer slack value が設定される。
prctl(2) の PR_SET_TIMERSLACK
の説明を参照。
- madvise(2) の MADV_DONTFORK
フラグでマークされたメモリーマッピングは、
fork()
によって引き継がれない。
- Memory in address ranges that have been marked with the madvise(2)
MADV_WIPEONFORK flag is zeroed in the child after a fork().
(The MADV_WIPEONFORK setting remains in place for those address
ranges in the child.)
- 子プロセスの終了シグナルは常に
SIGCHLD である (clone(2)
を参照)。
- ioperm(2)
で設定されるポートアクセス許可ビットは、子プロセスには継承されない。子プロセスでは、
ioperm(2)
を使って必要なビットをセットしなければならない。
以下の点についても注意すること:
- 子プロセスはシングルスレッドで生成される。つまり、
fork()
を呼び出したスレッドとなる。
親プロセスの仮想アドレス空間全体が子プロセスに複製される。
これにはミューテックス
(mutex)
の状態・条件変数・
pthread
オブジェクトが含まれる。
これが引き起こす問題を扱うには、
pthread_atfork(3)
を使うと良いだろう。
- After a fork() in a multithreaded program, the child can safely
call only async-signal-safe functions (see signal-safety(7)) until
such time as it calls execve(2).
- 子プロセスは親プロセスが持つ
オープンファイルディスクリプターの集合のコピーを引き継ぐ。
子プロセスの各ファイルディスクリプターは、
親プロセスのファイルディスクリプターに対応する
同じオープンファイル記述
(file description) を参照する
(open(2) を参照)。 これは
2
つのファイルディスクリプターが、ファイル状態フラグ・
ファイルオフセット、シグナル駆動
(signal-driven) I/O 属性 (fcntl(2)
における F_SETOWN, F_SETSIG
の説明を参照)
を共有することを意味する。
- 子プロセスは親プロセスが持つオープンメッセージキューディスクリプター
(mq_overview(7) を参照)
の集合のコピーを引き継ぐ。
子プロセスの各ファイルディスクリプターは、
親プロセスのファイルディスクリプターに対応する同じオープンメッセージキューディスクリプターを参照する。
これは 2
つのファイルディスクリプターが同じフラグ
(mq_flags)
を共有することを意味する。
- 子プロセスは、親プロセスのオープン済みのディレクトリストリームの集合
(opendir(3) 参照)
のコピーを継承する。
POSIX.1
では、親プロセスと子プロセス間の対応するディレクトリストリーム
はディレクトリストリームの位置
(positioning)
を共有してもよいとされている。
Linux/glibc
ではディレクトリストリームの位置の共有は行われていない。
返り値
成功した場合、親プロセスには子プロセスの
PID が返され、
子プロセスには 0
が返される。
失敗した場合、親プロセスに
-1
が返され、子プロセスは生成されず、
errno
が適切に設定される。
エラー
- EAGAIN
- A system-imposed limit on the number of threads was encountered. There are
a number of limits that may trigger this error:
- the RLIMIT_NPROC soft resource limit (set via setrlimit(2)),
which limits the number of processes and threads for a real user ID, was
reached;
- the kernel's system-wide limit on the number of processes and threads,
/proc/sys/kernel/threads-max, was reached (see
proc(5));
- the maximum number of PIDs, /proc/sys/kernel/pid_max, was reached
(see proc(5)); or
- the PID limit (pids.max) imposed by the cgroup "process
number" (PIDs) controller was reached.
- EAGAIN
- 呼び出し元は、スケジューリングポリシー
SCHED_DEADLINE
で動作しており、かつ
reset-on-fork
フラグがセットされていない。
sched(7) 参照。
- ENOMEM
- メモリーが足りないために、
fork()
は必要なカーネル構造体を割り当てることができなかった。
- ENOMEM
- An attempt was made to create a child process in a PID namespace whose
"init" process has terminated. See
pid_namespaces(7).
- ENOSYS
- fork()
はこのプラットフォームではサポートされていない
(例えば、メモリー管理ユニット
(MMU)
がないハードウェア)。
- ERESTARTNOINTR
(Linux 2.6.17 以降)
- System call was interrupted by a signal and will be restarted. (This can
be seen only during a trace.)
準拠
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
注意
Linux では、 fork() を
書き込み時コピー
(copy-on-write)
ページを用いて実装している。
したがって、fork
を行うことの唯一のデメリットは、
親プロセスのページテーブルを複製と
子プロセス自身のタスク構造の作成のための時間とメモリーが必要なことである。
glibc 2.3.3 以降では、 NPTL
スレッド実装の一部として提供されている
glibc のfork()
ラッパー関数は、
カーネルの fork()
システムコール
を起動するのではなく、clone(2)
を起動する。 clone(2)
に渡すフラグとして、伝統的な
fork()
システムコールと
同じ効果が得られるようなフラグが指定される
(fork() の呼び出しは、
flags に SIGCHLD
だけを指定して clone(2)
を呼び出すのと等価である)。
glibc のラッパー関数は
pthread_atfork(3)
を使って設定されている
任意の fork
ハンドラーを起動する。
関連項目
clone(2), execve(2), exit(2),
setrlimit(2), unshare(2), vfork(2), wait(2),
daemon(3), pthread_atfork(3), capabilities(7),
credentials(7)
この文書について
この man ページは Linux
man-pages
プロジェクトのリリース
5.10
の一部である。プロジェクトの説明とバグ報告に関する情報は
https://www.kernel.org/doc/man-pages/
に書かれている。