分岐されたプロセスは、書き込み時にマップされたすべてのメモリをコピーしますか?

分岐されたプロセスは、書き込み時にマップされたすべてのメモリをコピーしますか?

プロセスを分岐すると、親プロセスのメモリがマップされ、書き込み時にコピーされることがわかります。作成する必要がある部分だけをコピーしますか、またはマップされたメモリ全体をコピーしますか?

ベストアンサー1

短い答え:どちらもありません。カーネルはページ全体をコピーします。ページサイズは、使用しているアーキテクチャによって異なります(現在のアーキテクチャでは、複数のページサイズをサポートすることがよくあります)。 x86 64ビットアーキテクチャで実行されている場合、最も可能性の高いサイズは4KiBです。

より長い答え: カーネルとハードウェア仮想メモリシステムは、ページと呼ばれるフラグメントでメモリを処理します。たとえば、x86 64ビットアーキテクチャのデフォルトのページサイズは4KiBです。

この間、fork()親メモリ空間の大部分は子プロセスと共有されます。このメモリ空間はページで構成されます。各共有ページは、その期間中にカーネルによって読み取り専用として表示されますfork()

その後fork()完了誰でも親または子がメモリを修正しようとし、ページが読み取り専用としてマークされ、ハードウェアでページエラーを生成します。ページエラーは、カーネルに閉じ込められたCPU例外です(つまり、現在のプログラムの実行が停止し、CPUがカーネルで事前定義された例外ハンドラの実行を開始します)。

その後、カーネルはこれが書き込みコピーエラーであると判断し、新しいページを割り当てます。ページが読み取り/書き込みとしてマークされ、前のページの内容がコピーされます。その後、カーネルはそれをメモリ空間にマッピングします。その後、キャプチャコマンドでプロセス実行が再開されます。つまり、エラーの原因となったコマンドが再実行されます。今回はページが読み取り/書き込みとしてマークされ、コマンドはエラーなしで完了します。

このプロセスは、子供や親が共有ページに書き込むたびに繰り返されます。ページにCoWエラーが発生した後も、通常「その他」プロセスはまだ読み取り専用として表示されます(カーネルの実装によって異なります)。プロセスがここに書き込もうとすると、以前のようにエラーが生成されます。ただし、カーネルはページが共有されなくなったことに気づき、単に読み取り/書き込みとしてマークします。

おすすめ記事