RFORK(2)

名称
rfork - プロセスリソースの操作

ライブラリ
libc

書式
<unistd.h> int rfork(int flags)

解説
fork, vfork, rfork は、新しいプロセスが作成される唯一の方法です。 rfork() への引数 flags は、起動しているプロセス (親) のどのリソースが新しいプロセス (子) に よって共有されるか、またはそれらのデフォルト値に初期化されるかを選択します。 リソースにはオープンファイル記述子テーブル (これは、共有される場合、 プロセスが他のプロセスについてファイルを開閉することを 許容します) およびオープンファイルが含まれます。 flags は次の項目の論理和 (OR) です:
RFPROC
    設定されている場合、新しいプロセスが作成されます。 そうでない場合、変更が現在のプロセスに影響を及ぼします。 現在の実装は、このフラグが必ず設定されていることを要求します。
RFNOWAIT
    設定されている場合、子プロセスは親プロセスから分離されます。 終了時に、子プロセスは、親プロセスが集めるステータスを残しません。 wait(2) を参照してください。
RFFDG
    設定されている場合、起動側のファイル記述子テーブル ((intro) 2 を参照) がコピーされます。 そうでない場合、2 つのプロセスが 1 つのテーブルを共有します。
RFCFDG
    設定されている場合、新しいプロセスは新しいファイル記述子テーブルを持って 開始します。 RFFDG とは互いに排他的です。
RFMEM
    設定されている場合、 通常、ハードウェアのページテーブルを直接共有することで、 カーネルはアドレス空間全体を強制的に共有します。 子は、このような方法で、親プロセスが所有しているすべてのセグメントを、 それが普段共有可能であるか否かに関係なく、継承し共有します。 スタックセグメントは分割されない (親と子の両方が同じスタック上に復帰する) ので、RFMEM フラグを指定した rfork() は一般に、C 言語を含む高級言語から直接呼び出すことはできません。 共に設定可能なフラグは RFPROC だけです。 この問題を解決し、提供されたスタック上で新しいプロセスを 走らせるために補助関数が提供されています。 詳しくは rfork_thread(3) を参照してください。
RFSIGSHARE
    設定されている場合、カーネルは、親子間で sigacts 構造体を強制的に共有します。
RFLINUXTHPN
    設定されている場合、カーネルは、子についてのスレッド終了時に、 SIGCHILD の代わりに SIGUSR1 を返します。 これは特定の Linux クローン動作を模倣するためです。

共有ファイル記述子テーブル内のファイル記述子は、 明示的に閉じられるか、またはテーブルを 共有しているすべてのプロセスが終了するまで開いたままに保たれます。

RFPROC が設定されている場合、 親プロセス内で返される値は子プロセスのプロセス ID です。 子プロセス内で返される値は 0 です。 RFPROC がない場合、戻り値は 0 です。 プロセス ID の範囲は 1 から最大整数値 (int) です。 必要であれば、要求されたプロセスリソースが利用できるようになるまで rfork() は待機します。

fork() は、 rfork(RFFDG | RFPROC) への呼び出しとして実装可能ですが、後方互換性のために そのようには実装されていません。

戻り値
正常に完了した場合、 rfork() は、子プロセスに値 0 を返し、子プロセスのプロセス ID を親プロセスに 返します。 そうでない場合、子プロセスは作成されずに、値 -1 が親プロセスに返され、 エラーを示すためにグローバル変数 errno が設定されます。

エラー
rfork() は、次の場合に処理を失敗し、子プロセスは作成されません:

[EAGAIN]
    実行中のプロセスの合計数がシステムの課す制限を超過してしまいます。 制限は sysctl(3) MIB 変数 KERN_MAXPROC によって指定されます (スーパユーザを除いて、制限は実際には これより 10 個少なくなります)。

[EAGAIN]
    ユーザがスーパユーザではなく、1 人のユーザによる実行中の プロセスの合計数がシステムの課した制限を超過してしまいます。 制限は、 sysctl(3) MIB 変数 KERN_MAXPROCPERUID によって指定されます。

[EAGAIN]
    ユーザがスーパユーザではなく、リソースパラメータ RLIMIT_NOFILE に対応するソフトリソースの制限を超過してしまいます (getrlimit(2) を参照)。

[EINVAL]
    RFPROC フラグが指定されませんでした。

[EINVAL]
    RFFDG フラグと RFCFDG フラグの両方が指定されました。

[EINVAL]
    これまでに列挙されていないフラグが指定されました。

[ENOMEM]
    新しいプロセス用に十分なスワップ空間が不足しました。

関連項目
fork(2), intro(2), minherit(2), vfork(2), rfork_thread(3)

バグ
FreeBSD では、ネイティブな clone() ライブラリコールは未だに実装されていませんし、 現在の pthreads 実装は RFMEM を指定した rfork() を利用していません。 linux スレッドライブラリのネイティブポートである、 /usr/ports/devel/linuxthreads は RFMEM を利用して動作する clone() 呼び出しを含んでいます。 rfork_thread() ライブラリ関数は clone() の代わりとして利用することができます。

歴史
rfork() 関数は Plan9 ではじめて登場しました。