私は知っていますメモリ過剰割り当て私はそれを非常に嫌い、一般的に無効にします。はいいいえ考える設定値システムプロセス(例:実行中のプロセス)に基づくsudo
またはサフィックスただし、一般的なLinuxプロセスは、管理者権限なしで一部のユーザーによって一部のコマンドラインから起動されます。
よく書かれたプログラムは、使用可能なmalloc
メモリよりも多くのメモリを使用し、使用中にクラッシュする可能性がありますmmap
。malloc
メモリオーバーコミットがないと、malloc
ORはmmap
失敗し、よく書かれたプログラムはその失敗をキャッチします。malloc
誤って作成されたプログラム(失敗確認なしで使用)は、失敗の結果を使用するとクラッシュしますmalloc
。
確かに仮想アドレス空間mmap
(拡張malloc
)はRAMとは異なります(RAMはカーネルによって管理されているリソースです)。これ;プロセスの仮想アドレス空間が次に初期化されます。実行(2)mmap
& によって拡張されるのでsbrk
消費しません。まっすぐメモリのみ仮想メモリ)。
RAM使用の最適化は、次の方法で達成できます。クレイジーウェス(2)MADV_DONTNEED
(これは実際に必要なときにカーネルを使っていくつかのページをディスクに交換するようにヒントを与えるかもしれません。)過度にコミットしたいプログラムは、マッピング(2)そしてMAP_NORESERVE
。メモリオーバーコミットの私の理解は、すべてのメモリマップ(execve
またはを通じてmmap
)が暗黙的にMAP_NORESERVE
私の意見は、バグが多くのプログラムに役立つということです。しかし、IMHOは実際の開発者がすべきことです。いつも関連する仮想アドレス空間変更機能の確認と失敗malloc
(mmap
例:ここ)。私が調査したほとんどのフリーソフトウェアプログラムには、ソースコードにこれらのチェックが含まれています。xmalloc
機能....
実際には、合理的で便利な方法でメモリの再利用を要求して使用する実際のプログラム(一般的なLinuxディストリビューションにパッケージされています)はありますか?私はそれらを知らない!
メモリの再利用を無効にすると、どのような欠点がありますか?多くの古いUnix(たとえば、前世紀のSunOS4、SunOS5)にはこの機能がなく、IMHO malloc
(そしておそらく一般的なシステム全体のパフォーマンスmalloc
)もそれほど悪くありません(それ以降の改善はメモリの過剰割り当てには関係ありません)。
私はメモリ過剰割り当てが怠惰なプログラマの間違いだと思います。
プログラムユーザーは、いくつかのリソース制限を設定できます。制限設定(2)RLIMIT_AS
親プロセスによって呼び出されます(たとえば、ulimit
組み込み/bin/bash
;またはlimit
組み込み扱いにくいat
、または、、、、crontab
...などの最新の同等物または親プロセス(最終pid 1またはその最新プロセスbatch
まで)/sbin/init
システム変形)。
答え1
過剰コミットの理由は、物理RAMの使用率が低下するのを防ぐためです。プロセスによって割り当てられた仮想メモリの量と実際の物理ページフレームにマッピングされた仮想メモリの量には違いがあります。実際、プロセスが開始された後、RAMはほとんど予約されません。これは要求ページングによるものです。プロセスには仮想メモリレイアウトがありますが、仮想メモリアドレスから物理ページフレームへのマッピングは、メモリを読み書きするまで設定されません。
プログラムは通常、仮想メモリ空間全体を使用せず、影響を受けるメモリ領域はプログラム実行時に変更されます。たとえば、実行開始時にのみ実行される初期化コードを含むページフレームのマッピングを削除し、そのページフレームを他のマッピングに使用できます。
データにも同様に適用されます。プログラムが呼び出されると、malloc
データを格納するのに十分な大きさの連続した仮想アドレス空間が予約されます。ただし、物理ページフレームへのマッピングは、そのページが実際に使用されるまで設定されず、もしかして。または、プログラムスタックについて考えてみてください。各プロセスは、スタック専用の仮想メモリのかなり大きな連続領域(通常8 MB)を取得します。プロセスは通常、このスタックスペースの小さな部分のみを使用します。コンパクトでうまく動作するプログラムははるかに少なく使用されます。
Linuxコンピュータには、通常、ライフサイクルのさまざまな段階で実行されるさまざまな異機種プロセスがあります。統計的に言えば、どの時点でも、割り当てられた(または後でプログラムの実行時に割り当てられた)すべての仮想ページに対して一括マッピングは必要ありません。
厳密な非オーバーコミットシナリオでは、仮想ページを割り当てると、仮想アドレスページから物理RAMページフレームへの静的マッピングが生成されます。大量のRAMページフレームは何の目的もなく予約されているため、同時にはるかに少ないプログラムを実行できるシステムになります。
私はメモリを過度に使用することが危険であり、処理が困難なメモリ不足の状況につながる可能性があるという事実を否定しません。正しい妥協点を見つけることがすべてです。
答え2
あなたは、怠惰が問題と見なされないように言います。ダックプログラミング中:)。
大量のソフトウェアはシンプルさとメンテナンスのために最適化されており、メモリ不足の状態で生き残ることを非常に低い優先順位で処理します。割り当て失敗は通常、致命的と見なされます。メモリを消費するプロセスを終了すると、使用可能なメモリがなく、より多くのメモリを割り当てたり、包括的な事前割り当ての複雑さなしにシステムが進行できない状況を回避できます。
割り当てを確認して終了することと確認せずに競合することの違いはどのくらい微妙ですか? malloc() が成功したか失敗したかを確認しないプログラマを乱用すると非難することは不公平です。
割り当てが失敗しても「正しく」動作し続けると信頼できるソフトウェアはほんのわずかです。カーネルは通常生き残ることが期待されます。 sqliteによく知られた強力なテストこれには、特にさまざまな小型組込みシステムをサポートするように設計されているため、メモリ不足テストが含まれます。
通常の動作では、未使用のエラーパスとしてメモリ不足状態を正しく処理すると、メンテナンスとテストに大きな負担がかかります。努力が対応する利益を得られない場合は、他の場所に収益性の高い投資をすることができます。。
これが発生すると、最も一般的な障害の原因を処理するために大規模な割り当ての特殊なケースが生成されることがよくあります。
1つを許可一定額過度に使用おそらくこの文脈で最もよく見ることができます。これはLinuxの現在の基本的な妥協の一部です。
カーネルレベルのオーバーコミットを無効にする必要があることに注意してください。交換あなたが使用したいよりも多くを嫌う人もいます。時間が経つにつれて、RAMと回転するハードドライブとの間の速度ギャップはますます広くなるため、システムが許可したスワップスペースを実際に使用している場合は、しばしば「停止し始める」と説明できます。
答え3
私はJohan Myréenの答えに同意し、賛成します。ただし、問題を理解するのに役立つ追加の説明があります。
あまり使用されないRAMと仮想メモリを格納するために使用されるディスク領域であるスワップ領域を混同しているようです。後者はRAM領域とディスク領域から構成される。
プロセスが仮想メモリを予約して使用しています。彼らはそれがどこに保存されているのかわかりません。 RAMに存在しない一部のデータにアクセスする必要がある場合は、カーネルがデータページを使用可能にする操作を完了するまで、プロセス(またはスレッド)が一時停止されます。
RAM が必要な場合、カーネルは使用頻度の低いプロセス ページをディスク スワップ領域に格納し、一部の RAM を取得します。
プロセスがメモリを予約すると(たとえば、mallocなど)、オーバーコミットされていないオペレーティングシステムは、仮想メモリの未使用部分を使用不能としてマークします。これは、割り当てを実行するプロセスが実際にそのページにアクセスする必要があるときに予約されたページが存在することを保証することを意味します。
欠点は、他のプロセスでメモリが使用できないため、そのプロセスがページをページングするのを防ぐため、これらのプロセスが無効になるとRAMが無駄になることです。最も悪いことは、予約の合計がスワップ領域のサイズより大きい場合、データが含まれていなくても予約に一致するようにRAMページも予約されます。 RAMが不足しているため、これは非常に悪い状況です。両方書けないそして使用されません。最後に、最悪のシナリオは、もはや利用可能な仮想メモリ(スワップ+メモリ)がないため、大規模な予約を受け入れることができないことです。予約プロセスはしばしば中断されます。
一方、Linuxのように過度に使用されるオペレーティングシステムは、与えられた時間に仮想メモリが不足しないと確信しています。ほとんどのメモリ予約は許可されていますが(少し調整可能な非現実的なメモリ予約は許可されていません)、通常RAMとスワップリソースの使用率は高くなります。
これは、航空会社が座席を超過する予約に似ています。これにより搭乗率が向上しますが、一部の乗客は満足できない場合があります。航空会社が別のフライトを予約して報酬を受け取ることを望んでおり、Linuxは飛行機からより重い乗客を追い出すだけです。
通常、Linuxは怠惰な「ベストエフォート」方式でメモリを予約しますが、他の多くのオペレーティングシステムでは予約を保証します。
実際に起こるのは、多くの仮想メモリを使用するプログラムが最初に分岐してから実行する場合にのみオーバーコミットが意味があるということです。
4GBのRAMがあり、そのうち3GBは仮想メモリで、4GBはスワップ用に使用できるとしましょう。 4GBを予約しましたが、そのうち1GBのみを使用するプロセスがあります。ページングがないため、システムのパフォーマンスが良いです。オーバーコミットされていないオペレーティングシステムでは、フォーク後に4 GB以上の仮想メモリを予約する必要があり、3 GBしか残らないため、プロセスをフォークできません。
Linuxでは、このフォーク(またはレプリケーション)システムコールは正常に完了し(ただし、後でチートが発生します)、次の実行(存在する場合)の後にスケジュールされたが未使用の4 GBが何の害もなく解放されます。
答え4
殺害プロセスが理想的かもしれません
他の回答では、過度の約束がより効果的な方法について議論します。また、時にはプロセスを終了するのが正しいことです。
まず、コードを検討してくださいwhile(1){malloc(1)}
。過度に使用すると、最終的にはOOMキラーによって死にます。オーバーコミットしないと、使用可能なすべてのメモリが消費され、システムがクラッシュします。
余分なコミットのない解決策は、cgroupを使用してメモリ量を制限することです。しかし、これは合理的なデフォルト値を選択する課題を残します。時には合理的なデフォルト値がない場合もあります。いくつかの科学タスクは一時停止の問題を解決するのと同じくらい難しいので、完了するのにどれだけのメモリと時間が必要かを知ることができません。科学ユーザーが利用可能なメモリ内のすべてのバイトを安全に割り当てるようにすることで、より重要なプロセスにメモリが必要な場合は、OOMキラーがメモリを中断することを知ることで成功の可能性を最大化できます。