中間ステップでは、外部プログラムに認識されることなく、子プロセスに共有リソースを設定できます。標準的な例は、パイプの構築です。
// read output of "ls"
// (error checking omitted for brevity)
int pipe_fd[2];
pipe(&pipe_fd);
if (fork() == 0) { // child:
close(pipe_fd[0]); // we don't want to read from the pipe
dup2(pipe_fd[1], 1); // redirect stdout to the write end of the pipe
execlp("ls", "ls", (char *) NULL);
_exit(127); // in case exec fails
}
// parent:
close(pipe_fd[1]);
fp = fdopen(pipe_fd[0], "r");
while (!feof(fp)) {
char line[256];
fgets(line, sizeof line, fp);
...
}
fork
パイプへの標準出力のリダイレクトが、との間の子でどのように行われるかに注意してくださいexec
。もちろん、この単純なケースでは、適切なパラメーターが与えられれば、これを自動的に実行するスポーン APIが存在する可能性があります。しかし、このfork()
設計では、子のプロセスごとのリソースを任意に操作できます。つまり、不要なファイル記述子を閉じたり、プロセスごとの制限を変更したり、権限を削除したり、シグナル マスクを操作したりできます。がなければfork()
、プロセスを生成するための API は非常に太るか、あまり役に立たなくなります。実際、競合するオペレーティング システムの呼び出しを生成するプロセスは、通常、その中間に位置します。
メモリの浪費に関しては、コピー オン ライト技術で回避されます。fork()
子プロセスに新しいメモリを割り当てませんが、ページが書き込まれた場合にのみページのコピーを作成するように指示して、子を親のメモリにポイントします。これによりfork()
、「目次」をコピーするだけで済むため、メモリ効率が向上するだけでなく、高速になります。