親プロセスが子プロセスを fork しようとすると、errno=12 (メモリ不足) で失敗します。親プロセスは Linux 3.0 カーネル - SLES 11 で実行されます。子プロセスをフォークする時点で、親プロセスはすでに RAM の約 70% (180GB/256GB) を使用しています。この問題の回避策はありますか?
アプリケーションは C++ で作成され、g++ 4.6.3 でコンパイルされています。
親プロセスが子プロセスを fork しようとすると、errno=12 (メモリ不足) で失敗します。親プロセスは Linux 3.0 カーネル - SLES 11 で実行されます。子プロセスをフォークする時点で、親プロセスはすでに RAM の約 70% (180GB/256GB) を使用しています。この問題の回避策はありますか?
アプリケーションは C++ で作成され、g++ 4.6.3 でコンパイルされています。
システムで仮想メモリのオーバーコミットが防止されている可能性があります。
それが防止された場合、仮想メモリは物理 RAM のサイズ + スワップよりも大きくすることはできません。許可されている場合、仮想メモリは RAM + スワップよりも大きくなる可能性があります。
プロセスが fork すると、プロセス (親と子) は 2*180GB の仮想メモリを持つことになります (スワップがない場合は多すぎます)。
したがって、次の方法でオーバーコミットを許可します。
echo 1 > /proc/sys/vm/overcommit_memory
子プロセスがすぐに実行する場合、または親が自分のメモリに書き込みすぎる前に割り当てられたメモリを解放する場合に役立ちます。したがって、両方のプロセスがすべてのメモリを使用し続けると、メモリ不足キラーが動作する可能性があることに注意してください。
proc(5) の man ページには次のように書かれています。
/proc/sys/vm/overcommit_memory
このファイルには、カーネルの仮想メモリ アカウンティング モードが含まれています。値は次のとおりです。 0: ヒューリスティック オーバーコミット (これがデフォルト) 1: 常にオーバーコミットし、チェックしない 2: 常にチェックし、オーバーコミットしない
モード 0 では、MAP_NORESERVE を指定した mmap(2) の呼び出しはチェックされず、デフォルトのチェックは非常に弱く、プロセスが「OOM-killed」になる危険性があります。Linux 2.4 では、0 以外の値はモード 1 を意味します。モード 2 (Linux 2.6 以降で使用可能) では、システムの仮想アドレス空間の合計は (SS + RAM*(r/100)) に制限されます。ここで、SS はスワップ スペース、RAM は物理メモリのサイズ、r はファイル /proc/sys/vm/overcommit_ratio の内容です。
詳細はこちら: SLES でのメモリのオーバーコミット
fork
-ing は、プロセスの書き込み可能なページを書き込み時にコピーするため、リソースを必要とします。fork(2)の man ページをもう一度読んでください。
少なくとも、巨大な一時スワップ ファイルを提供できます。(十分なスペースのあるファイルシステムで)巨大なファイル$SWAPFILE
を作成できます
dd if=/dev/zero of=$SWAPFILE bs=1M count=256000
mkswap $SWAPFILE
swapon $SWAPFILE
それ以外の場合は、たとえば、プログラムを別の方法で設計することができます。たとえば、mmap
いくつかの大きなファイルを -ing (およびmunmap
フォークの直前で-ing し、その後で再度 -ing)、またはより単純にプログラムの最初から-ed シェルmmap
を開始することができます。popen
または、p2open
-ed を使用するか、明示的にpipe
-s を使用して (おそらく、la のような多重化呼び出しpoll
も役立つでしょう)、後でコマンドを発行します。
あなたのプログラムが何をしているのか、なぜそれほど多くのメモリを消費するのか、そしてなぜ何が分岐しているのかについての考えがあれば、もっと役立つかもしれません...
詳細については、高度な Linux プログラミングをお読みください。
fork
バックトレースを表示するためだけに実行する場合は、最近の GCC の libbacktraceやWolf のgdb
libbacktrace などのより単純な代替手段を検討してください...