私自身の質問に答えて申し訳ありませんが、解決策の記録が欲しいです。おがくずでリンクされた記事には、必要なものが含まれています。
- カーネルは、割り当て可能なメモリが不足すると、メモリ不足マネージャー (Linux カーネルでは mm/oom_kill.c) をアクティブにします。
- OOM マネージャーは、いくつかのヒューリスティックを使用して、どのプロセスを強制終了するかを決定します。プロセスの総実行時間は死亡の可能性を減らしますが、割り当てられたメモリは増加します。他にも要因はありますが、私には関係ありません。
- プロセスを選択した後、OOM は SIGTERM を送信します。
私の場合、メモリを大量に消費しているプロセスを除くすべてのプロセスが強制終了される理由は 2 つあります。
私のプロセスは、メモリを割り当てている領域で SIGTERM を無視します。これは、プロセスがこの時間中に他の多くのシグナルを積極的に受信しているため、および/またはプロセスが残りの時間の大部分で I/O をブロックしているためである可能性があります。いずれにせよ、SIGTERM を無視します。
通常、すべてのメモリを占有しているプロセスは長時間実行されており、RAM が数時間蓄積されています。他のプロセスの約 4 倍の処理能力がありますが、ランタイムが長いため (他のプロセスより数百倍長い)、OOM マネージャーが他のプロセスを選択して最初に終了させる可能性があります。
ソリューション:
ランニング:
ulimit -v memamount
特定のユーザーに対して、ユーザーが単一のプロセスで割り当てることができるメモリの最大量を memamount に変更します。これにより、OOM マネージャーがアクティブ化されなくなる可能性があります。代わりに、malloc 呼び出しが失敗しますが、これは検出できます。
2: 正常にクリーンアップする SIGTERM のハンドラーを作成すると役立つ場合がありますが、これは、OOM が実際に SIGTERM をプロセスに送信しており、プロセスが SIGTERM を無視するか、受信に失敗している場合に限られます。
3: コード内からメモリ制限を設定します (C):
//resource limit structure with both hard and soft max set to 2GB.
struct rlimit memmax; memmax.rlim_max=0x7FFFFFFF; memmax.rlim_cur = 0x7FFFFFFF;
setrlimit(RLIMIT_MEMLOCK,&memmax); //set maximum virtual memory space to 2GB.