下記の比較表を参考にして、fork()とvfork()の違いを見つけてみましょう。
比較表
比較基準 | フォーク() | vfork() |
---|---|---|
基本 | 子プロセスと親プロセスには別々のアドレススペースがあります。 | 子プロセスと親プロセスは同じアドレス空間を共有します。 |
実行 | 親プロセスと子プロセスは同時に実行されます。 | 子プロセスが実行を完了するまで、親プロセスは中断されたままになります。 |
変形 | 子プロセスがアドレス空間内のページを変更した場合、アドレス空間は別のものであるため、親プロセスには見えません。 | 子プロセスがアドレススペース内のページを変更した場合、それらは同じアドレススペースを共有しているので、親プロセスから見えます。 |
コピーオンライト | fork()は、コピーオンライトを使用して、親と子がいずれかが共有ページを変更するまで同じページを共有します。 | vfork()はコピーオンライトを使用しません。 |
fork()の定義
fork()は新しいプロセスを作成するためのシステムコールです。 fork()呼び出しによって作成された新しいプロセスは、fork()システムコールを呼び出したプロセスの子プロセスです。 子プロセスのコードは、その親プロセスのコードと同じです。 子プロセスの作成後、親プロセスと子プロセスの両方がfork()の後の次のステートメントから実行を開始し、両方のプロセスが同時に実行されます。
親プロセスと子プロセスは別々のアドレス空間を持ちます 。 したがって、いずれかのプロセスがコード内のステートメントまたは変数を変更したとき。 他のプロセスコードには反映されません。 子プロセスがコードを変更しても親プロセスには影響しないとしましょう。
作成後の一部の子プロセスはすぐにexec()を呼び出します。 exec()システムコールは、プロセスをそのパラメータで指定されたプログラムに置き換えます。 その場合、子プロセスの別のアドレス空間は役に立ちません。 ここでの1つの選択肢はコピーオンライトです。
コピーオンライトにより、親プロセスと子プロセスは同じアドレススペースを共有できます。 いずれかのプロセスがアドレス・スペース内のページに書き込みを行うと、両方のプロセスが独立して機能するようにアドレス・スペースのコピーが作成されます。
vfork()の定義
fork()の修正版はvfork()です。 vfork()システムコールは新しいプロセスを作成するためにも使用されます。 fork()と同様に、ここでも作成された新しいプロセスはvfork()を呼び出したプロセスの子プロセスです。 子プロセスコードも親プロセスコードと同じです。 ここでは、両方のプロセスが使用するアドレス空間を共有しているため、子プロセスはその実行が完了するまで親プロセスの実行を中断します。
子プロセスと親プロセスは同じアドレス空間を共有します 。 いずれかのプロセスがコードを変更すると、同じページを共有している他のプロセスから見えます。 親プロセスがコードを変更したとしましょう。 子プロセスのコードに反映されます。
vfork()を使用しても、子プロセスと親プロセスに別々のアドレススペースは作成されません。 したがって、子プロセスが作成直後にexec()を呼び出す場所に実装する必要があります。 したがって、アドレススペースを無駄にすることはなく、プロセスを作成するための効率的な方法です。 vforkはコピーオンライトを使用しません。
fork()とvfork()の主な違い
- forkとvforkの主な違いは、 forkによって作成された子プロセスは、親プロセスとは別のメモリスペースを持っているということです。 ただし、 vforkシステムコールによって作成された子プロセスは、その親プロセスと同じアドレス空間を共有します。
- forkを使用して作成された子プロセスは、親プロセスと同時に実行されます。 一方、vforkを使用して作成された子プロセスは、実行が完了するまで親プロセスの実行を中断します。
- 親プロセスと子プロセスのメモリスペースは別々のものであるため、いずれかのプロセスによる変更は他のページに影響を与えません。 ただし、親プロセスと子プロセスは同じメモリアドレスを共有しているため、どのプロセスによって行われた変更もアドレス空間に反映されます。
- システムコールfork()は代替方法としてコピーオンライトを使用します 。これにより、子プロセスと親プロセスのいずれかがページを変更するまで同じプロセスを共有できます。 一方、vforkはコピーオンライトを使用しません。
結論:
vfork()システムコールは、子プロセスがfork()を使用して作成した直後にexec()を呼び出すときに実装する必要があります。 子プロセスと親プロセス用の別々のアドレス空間はここでは役に立ちません。