1. fork()関数
- 同じプログラムの処理を複数のプロセスに分けて処理するために使用
- fork()を実行すると、発行元プロセス(親プロセス)を元に新たにプロセスを生成する(子プロセス)
- プロセス生成のイメージ
- 子プロセス用のメモリ領域を作成して、親プロセスのメモリをコピー
- 親プロセスと子プロセスは違うコードを実行するように分岐する。
- これには、fork()関数の戻り値が親プロセスと子プロセス間で異なることを利用する。
- 親プロセス側ではfork()の戻り値は子プロセスのPIDとなる。
- 子プロセス側ではfork()の戻り値は"0"となる。
2. exec()関数
- 全く別のプログラムを生成する場合に使用
- プロセス生成の流れ
- 実行ファイルを読み出して、プロセスのメモリマップに必要な情報を読み出す
- 現在のプロセスメモリを新しいプロセスのメモリデータで上書きする
- 新しいプロセスの最初の命令から実行開始する。
- つまりexec()を実行するとその実行元のメモリ情報は全て置き換えられる。
3. Fork-Exec
- Fork-Execは、Linuxで一般的に使われる手法であり、新たなプログラムをプロセスとして実行する。
- fork()によって子プロセスが親プロセスのコピーとして生成され、exec()を実行することで(子プロセス)自身の内容を置き換える。
- 子プロセスがexec()を呼び出すと、そのアドレス空間の内容は全て失われ、指定されたプログラムを実行するためのアドレス空間のマッピングが設定される。これをオーバーレイと呼ぶ。
- アドレス空間は全て置き換えられるが、オープン済みファイルのファイル記述子群は close-on-exec が指定されたときだけ exec()時に自動的にクローズされる。
- この特徴を利用して、fork()を呼び出す前にパイプを作成しておき、exec()で指定された新しいプログラムとの通信を行うというUNIX特有の手法が実現されている。