作業中のターゲット プラットフォームの 1 つは、Linux を実行するリソースに制約のあるミニ サーバーです (カーネル 2.6.13、古い Fedora Core に基づくカスタム ディストリビューション)。アプリケーションは Java (Sun JDK 1.6_04) で書かれています。Linux OOM キラーは、メモリ使用量が 160MB を超えるとプロセスを強制終了するように構成されています。負荷が高い場合でも、アプリケーションが 120MB を超えることはなく、アクティブな他のネイティブ プロセスと合わせて、OOM の制限内に収まっています。
しかし、Java から外部プロセスを実行する標準的な方法である Java Runtime.getRuntime().exec() メソッドは、Linux で特に不幸な実装をしており、生成された子プロセスが (一時的に) 同じ量のアドレス空間がコピーされるため、親プロセスとしてのメモリ。最終的な結果として、Runtime.getRuntime().exec() を実行するとすぐに、アプリケーションが OOM キラーによって強制終了されます。
現在、別のネイティブ プログラムですべての外部コマンドの実行を行い、ソケットを介してそのプログラムと通信することで、この問題を回避しています。これは最適とは言えません。
この問題についてオンラインで投稿した後、Linux の「新しい」バージョンでは、コピー オン ライトを使用して posix fork() メソッドを実装しているため、これは発生しないはずであるというフィードバックを受け取りました。おそらく、必要なページのみをコピーすることを意味します。アドレス空間全体をすぐに変更するのではなく、必要なときに変更します。
私の質問は次のとおりです。
- これは本当ですか?
- これはカーネル、libc 実装、または完全に別の場所にあるものですか?
- fork() のコピー オン ライトは、どのバージョンのカーネル/libc/whatever から利用できますか?