fork()
システムコールは、実行中のプロセスから子プロセスのクローン。2つのプロセスは、PIDを除いて同一です。
当然、プロセスがヒープに書き込むのではなく、ヒープから読み取るだけの場合、ヒープのコピーはメモリの大きな浪費になります。
プロセスヒープ全体がコピーされますか?書き込みのみがヒープコピーをトリガーするように最適化されていますか?
fork()
システムコールは、実行中のプロセスから子プロセスのクローン。2つのプロセスは、PIDを除いて同一です。
当然、プロセスがヒープに書き込むのではなく、ヒープから読み取るだけの場合、ヒープのコピーはメモリの大きな浪費になります。
プロセスヒープ全体がコピーされますか?書き込みのみがヒープコピーをトリガーするように最適化されていますか?
回答:
全体のは、fork()
書き込みにはmmap /コピーを使用して実装されています。
これは、ヒープだけでなく、共有ライブラリ、スタック、BSSエリアにも影響します。
結果として、結果の2つのプロセス(親と子)が実際にメモリ範囲への書き込みを開始するまで、フォークは非常に軽量な操作であることを意味します。この機能は、フォークボムの致死性に大きく貢献します。ページの複製と差別化でカーネルが過負荷になる前に、プロセスが多すぎることになります。
最新のOSで、カーネルがハードコピーを実行する操作の例(デバイスドライバーは例外)を見つけるのは困難です。VM機能を採用するのは、はるかに簡単で効率的です。
execve()
「バイナリ/ ld.so /その他もろもろ、実行に続いてのmmapください」本質的に-とVMは、RAM、実行するプロセスの実際の負荷を処理します。ローカルの初期化されていない変数は「ゼロページ」からmmapされます-ゼロを含む特別な読み取り専用コピーオンライトページ、ローカルの初期化された変数はバイナリファイル自体からmmapされます(コピーオンライト、再び)等
Linuxカーネルfork()
は、呼び出されたときにCopy-on-Writeを実装します。syscallが実行されると、親と子が共有するページは読み取り専用としてマークされます。
読み取り専用ページで書き込みが実行されると、メモリは2つのプロセス間で同一ではなくなるため、コピーされます。したがって、読み取り操作のみが実行されている場合、ページはまったくコピーされません。
fork()
呼び出し後の次の命令からではなく、開始から実行する同じプログラムのインスタンスをより多く作成するようです。
/proc/self/pagemap
は、テストの目的のために、仮想アドレスから物理ページへのマッピングを決定するために使用していました。予想どおり、孫と孫だけが共有ページを書き込む場合、親と元の子は引き続き共有ページを共有します。孫だけがプライベートコピーになります。