最終更新:2021-02-17 (水) 03:36:55 (1157d)  

fork
Top / fork

プロセスのコピーを生成

メモ

  • Linuxでは子プロセスを生成するために fork システムコールを使って,自分のプロセスのコピーを生成する方法をとる
  • 別のプログラムを子プロセスとして実行する場合でも自分のコピーを生成して実行しなければならない

pid_t pid;

pid = fork();

if (pid == 0) {
	/* 子プロセス:
	* fork()が0を返す場合、子プロセスである
	* 1秒に1ずつ、10まで数える。
	*/
	int j;
	for (j=0; j < 10; j++) {
		printf("child: %d\n", j);
		sleep(1);
	}
	exit(0); /* exit() を使わない点に注意 */
} else if(pid > 0) { 
	/* 親プロセス:
	* 0以外の場合、親プロセスである
	* ここでも10まで数える
	*/
	int i;
	for (i=0; i < 10; i++) {
		printf("parent: %d\n", i);
		sleep(1);
	}
} else {   
	/* エラー処理 */
	fprintf(stderr, "couldn't fork");
	exit(1);
}

プロセス

親プロセス

  • fork>0
  • 失敗したときは-1

子プロセス

  • fork=0

子プロセスのプログラムの内容を新しいプログラムで上書きする

メモリ

  • 本来ならばOSが子プロセスのために親プロセスの持つ全ページを物理メモリ上の別の位置にコピーすることになる。しかし、場合によってはその必要はない。
    • execで他のファイルを実行したりすぐに終了する場合

コピーオンライト

  • fork時に親プロセスのページ群を子プロセスにコピーしない。その代わりページ群は親プロセスと子プロセスの間で共有される。
  • 親子いずれかのプロセスがページの内容を更新しようとしたとき、そのページだけコピーを作成し、書き込もうとしたプロセスの当該ページだけが更新される。
  • 書き込んだプロセスはその後その新たにコピーしたページを使用する。

スタック

  • スタックについてもコピーオンライト

メモ

  • forkはそれを実行したプロセスの子プロセスを作成する.子プロセスは親プロセスのコピー
  • プロセスをどこまで実行したか(プログラムカウンタ?)もコピーされるので、子プロセスはforkの返り値が返るところから実行される
  • ファイルディスクリプタなどもオープンされていればそのままコピーされる。コピーされないのはpidやppidとファイルロックやサスペンド中のシグナルぐらい
  • そして、そのforkの返り値によって,プロセスは自分が親プロセスか子プロセスかを知ることができる
  • forkが呼び出されると、子プロセスのためのアドレス空間が新たに作成される。子プロセスのアドレス空間には親プロセスが持っていた全セグメントのコピーがあるが、コピーオンライト機能によって実際の物理メモリの確保は遅延される。親プロセスと子プロセスは独立して実行される。

関連

参考