8

以前に使用されていたが現在は必要ないメモリ用に、プロセスで予約された仮想アドレス空間を維持したいと考えています。ホスト カーネルが Linux であり、オーバーコミットを防ぐように構成されている状況に興味があります (これは、コミットされたすべてのメモリの詳細なアカウンティングによって行われます)。

アプリケーションが使用しなくなったデータが物理メモリを占有したり、ディスクにスワップされたりするのを防ぎたい場合 (いずれにしてもリソースを浪費する)、madvise不要なカーネルを削除するか、そのmmap上に新しいゼロ ページを重ねることができます。しかし、これらのアプローチのどちらも、コミット済みとしてカウントされるメモリの量を必ずしも削減するわけではなく、他のプロセスが使用できなくなります。

ページを読み取り専用としてマークされた新しいゼロ ページに置き換えるとどうなりますか? 私の意図は、それらがコミットされたメモリにカウントされず、後でmprotectそれらを書き込み可能にするために使用できること、およびそれらを書き込み可能にするとコミットされたメモリの制限を超えると失敗することです。私の理解は正しいですか?これは機能しますか?

4

2 に答える 2

1

ページを使用していない場合 (読み取りまたは書き込み)、アドレス空間にコミットされません (予約済みのみ)。

しかし、あなたのアドレス空間は限られているので、好きなようにプレイすることはできません。

たとえば、"nul page/guard page" (アクセスのない匿名メモリ) の挿入が原因で、多数の割り当てで失敗する可能性がある ElectricFence を参照してください。これらのスレッドを見てください:「mprotect() が失敗しました: メモリを割り当てることができません」: http://thread.gmane.org/gmane.comp.lib.glibc.user/538/focus=976052

于 2011-02-10T14:58:22.640 に答える
1

Linux では、オーバーコミットが無効になっていないと仮定すると、MAP_NORESERVEフラグ to を使用できますmmap。これにより、問題のページがアクセスされる前に割り当てられたメモリとして考慮されなくなります。オーバーコミットが完全に無効になっている場合は、以下の複数マッピング ページを参照してください。

ゼロ ページに対する Linux の動作は、過去に何度か変更されていることに注意してください。一部のカーネル バージョンでは、ページを読み取るだけでページが割り当てられます。その他の場合は、書き込みが必要です。保護フラグによって割り当てが直接行われるわけではないことに注意してください。ただし、割り当てが誤ってトリガーされるのを防ぐことができます。mprotectしたがって、最も信頼性の高い結果を得るには、 with を使用してページにアクセスすることをまったく避ける必要がありますPROT_NONE

移植性の高いもう 1 つのオプションとして、同じページを複数の場所にマップできます。つまり、空の一時ファイルを作成して開き、ftruncate適切な数のページへのリンクを解除してからmmap、ファイルのオフセット 0 で繰り返します。これにより、メモリがプログラムのメモリ使用量に対して 1 回だけカウントされることが確実に保証されます。MAP_PRIVATEページへの書き込み時に自動再割り当てを行うこともできます。

ただし、これは手法よりもメモリ使用量が高くなる可能性がありますMAP_NORESERVE(カーネル追跡データと一時ファイル自体のページの両方)。そのためMAP_NORESERVE、可能な場合は代わりに使用することをお勧めします。この手法を使用する場合は、マップされる領域を適度に大きくするようにしてください ( /dev/shmLinux の場合は、実際のディスク IO を回避するために入れてください)。個々のmmap呼び出しは、それを追跡するために一定量の (スワップ不可の) カーネル メモリを消費するため、カウントダウンを維持することをお勧めします。

于 2011-02-10T15:05:28.617 に答える