1. ホーム
  2. linux

[解決済み】fork()、vfork()、exec()、clone()の違いについて)

2022-04-07 16:38:30

質問

Googleでこの4つの違いを探したのですが、膨大な情報があるかと思いきや、本当に4つのコールをしっかり比較したものがありませんでした。

そこで、これらのシステムコールの違いが一目でわかるような基本的な情報をまとめようとしたところ、以下のような結果が得られました。この情報は正しいのか、何か重要なことを見逃していないか?

Fork : fork 呼び出しは基本的に現在のプロセスの複製を作成し、ほぼすべての面で同一にします (実装によってはリソース制限など、すべてがコピーされるわけではありませんが、できるだけ近いコピーを作成することを目的としています)。

新しいプロセス(子)は異なるプロセスID(PID)を取得し、古いプロセス(親)のPIDをその親PID(PPID)として持ちます。2つのプロセスは全く同じコードを実行しているので、forkの戻りコードでどちらがそうなのかわかります。もちろん、これはすべてfork呼び出しがうまくいくことを前提としています。そうでない場合、子は作成されず、親はエラーコードを受け取ります。

Vfork : vfork と fork の基本的な違いは、vfork() で新しいプロセスを作成すると、親プロセスが一時的に停止し、子プロセスが親のアドレス空間を借用する可能性があるということです。この奇妙な状態は、子プロセスが終了するか、execve()を呼び出すまで続き、その時点で親プロセスが終了します。 プロセスは継続されます。

つまり、vfork()の子プロセスは、親プロセスの変数を予期せず変更しないように注意する必要があるのです。特に、子プロセスは vfork() 呼び出しを含む関数から戻ってはいけませんし、 exit() を呼んでもいけません (終了する必要がある場合は、 _exit() を使うべきです; 実は、これは通常の fork() の子プロセスにも当てはまります)。

Exec : execコールは、基本的に現在のプロセス全体を新しいプログラムに置き換えるための方法です。exec() は現在のプロセスを、関数が指す実行ファイルに置き換えます。exec()エラーが発生しない限り、制御が元のプログラムに戻ることはありません。

Clone : クローンはフォークと同様に、新しいプロセスを作成します。fork とは異なり、これらの呼び出しによって、子プロセスは呼び出し元のプロセスと、メモリ空間、ファイル記述子のテーブル、シグナルハンドラのテーブルといった実行コンテキストの一部を共有することができます。

cloneで子プロセスを生成すると、関数アプリケーションfn(arg)が実行されます。(これは、元のフォーク呼び出しの時点から子プロセスで実行を続けるフォークとは異なる)。fn引数は子プロセスが実行開始時に呼び出す関数へのポインタである.arg引数はfn関数に渡される。

fn(arg)関数のアプリケーションが戻ると、子プロセスは終了する。fn が返す整数が子プロセスの終了コードである。子プロセスは、exit(2) を呼び出すか、致命的なシグナルを受け取った後に明示的に終了させることもできます。

情報取得フォーム :

お時間を割いていただきありがとうございます ! :)

どのように解決するのですか?

  • vfork() は時代遅れの最適化です。 良いメモリ管理の前に。 fork() は親メモリの完全なコピーを作成するため、かなりコストがかかります。 fork() が続き、その後に exec() これは、現在のメモリーマップを破棄して新しいメモリーマップを作成するもので、無駄な出費であった。 現在では fork() はメモリをコピーするのではなく、単に"copy on write"と設定されているだけですから。 fork() + exec() と同じように効率的です。 vfork() + exec() .

  • clone() が使用するシステムコールです。 fork() 両者の違いは、どのデータ構造(メモリ空間、プロセッサの状態、スタック、PID、オープンファイルなど)が共有されているかどうかだけです。