web-dev-qa-db-ja.com

プロセスがフォークすると、その仮想メモリまたは常駐メモリがコピーされますか?

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

仮想メモリ(プロセスが要求したもの)と常駐メモリ(実際に使用されているメモリ)について話しているメモリフットプリントはどれですか。

動機:スワップスペースが制限されたデバイスと、仮想メモリと常駐メモリのフットプリントに大きな違いがあるアプリケーションがあります。メモリ不足のため、アプリケーションはforkできません。仮想フットプリントのサイズを小さくすることが役立つかどうかを確認したいと考えています。

12

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

これは、コピーオンライトと呼ばれます。

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

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

12
kasperd

心配しないでください。遅延コピー(コピーオンライト)を作成します。両方のプロセスの仮想メモリアドレスは最初は同じページを指しますが、フォークされたプロセスがそれを変更しようとすると、実際にはページの物理コピーが作成されます(それ以降、そのページはRAM内の2つの場所に存在します)。

レポートされたメモリフットプリントのどれも、実際にRAMがプロセスで使用されている量を示していない。仮想メモリに関するスワッピング、メモリ共有、およびその他の問題のため、確実に知ることは不可能である。メモリ空間の一部は共有ライブラリ(それらをカウントする場所?)、一部は非RAMメモリ(他のハードウェアデバイス)を参照、一部は現在スワップアウトされている、一部はまだコピーされていない(コピーオンライト)などこれを読んでください:

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

5
orion

カーネル設定あり

/ 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に設定した場合、forkは書き込み時にコピーされます。コピーオンライトは、アプリが分岐すると、両方のコピーがメモリページを共有することを意味します。

ほとんどのディストリビューションでは、オーバーコミットは0です。ただし、2に設定すると、すべてのメモリページは実メモリによって完全にサポートされ、場合によっては高メモリプレッシャーの下でより安定しますが、一部のプログラム(私はgitkに直面しました)はオーバーコミットでは失敗します。

5
gena2x