プロセスが分岐すると、仮想メモリまたは常駐メモリがコピーされますか?

プロセスが分岐すると、仮想メモリまたは常駐メモリがコピーされますか?

Linuxで新しいプロセスを作成する標準的な方法は、親プロセスのメモリスペースをコピーして呼び出すexecvまで、子プロセスの環境になることです。

仮想メモリ(プロセスで要求されたメモリ)または常駐メモリ(実際に使用されているメモリ)のどちらのメモリ空間を言いますか?

同期:スワップ領域が制限されているデバイスと、仮想メモリ領域と常駐メモリ領域の差が大きいアプリケーションがあります。メモリ不足のためにアプリケーションが分岐することができず、仮想スペースのサイズを減らすのに役立つことを確認したいと思います。

答え1

最新のシステムでは、forkシステムコールを使用した結果、実際にメモリはコピーされません。ページテーブルはすべて読み取り専用としてマークされているため、カーネルコードに最初に書き込もうとするとトラップが発生します。コピーは、最初のプロセスが書き込みを試みたときにのみ発生します。

これを記録中にコピーと呼びます。

ただし、コミットされたアドレス空間を追跡する必要があるかもしれません。カーネルがページをコピーするときに使用可能なメモリまたはスワップがない場合は、メモリを解放するためにいくつかのプロセスを終了する必要があります。これは常に望ましいとは限らないので、カーネルがコミットしたメモリ量を追跡することが可能です。

カーネルが使用可能なメモリ+スワップ領域よりも多くのメモリをコミットしている場合、フォークを呼び出そうとするとエラーコードが表示されることがあります。空き容量が十分な場合、カーネルは、親プロセスの全体の仮想サイズをフォーク後の両方のプロセスにコミットします。

答え2

心配しないでください。遅延コピー(記録中のコピー)を実行します。両方のプロセスの仮想メモリアドレスは最初は同じページを指しますが、分岐したプロセスがそれを変更しようとすると実際にページの物理コピーが作成されます(この時点からページは2つのRAMの場所にあります)。

報告されたメモリスペースは、実際にプロセスが使用するRAMの量を知らせません。仮想メモリの交換、メモリ共有などの問題で確実に判断することは不可能です。メモリ空間の一部は共有ライブラリであり(どこで計算されますか?)、一部はRAMではなくメモリ(その他のハードウェアデバイス)を参照し、一部は現在置き換えられており、一部はまだコピーされておらず(記録中のコピー)、一部はすぐになりますです。これを読んでください:

https://lwn.net/Articles/642202/

答え3

カーネル設定があります

/proc/sys/vm/overcommit_memory

優れた引用記事:

Since 2.5.30 the values are: 0 (default): as before: guess about how much  
overcommitment is reasonable, 1: never refuse any malloc(), 2: be precise 
about the overcommit - never commit a virtual address space larger than swap 
space plus a fraction overcommit_ratio of the physical memory. Here 
/proc/sys/vm/overcommit_ratio (by default 50) is another user-settable 
parameter. It is possible to set overcommit_ratio to values larger than 100. 
(See also Documentation/vm/overcommit-accounting.)

これは通常のmallocだけでなくフォークでも機能します。つまり、0に設定すると、フォークは書き込み時にコピーされます。記録中のコピーは、アプリケーションがフォークされると、下位バージョンまたは元のバージョンがメモリ変更を開始するまで、両方のコピーがメモリページを共有することを意味します。

ほとんどのディストリビューションでは、乱用はゼロであることがわかります。ただし、2に設定すると、すべてのメモリページが物理メモリによって完全にサポートされ、場合によっては高いメモリ圧力でより安定していますが、過剰なコミットに依存するいくつかのプログラム(gitkに遭遇しました)は失敗します。

関連情報