2011-02-07 7 views
13

64ビットアドレッシングのためのアドレス空間は絶対に巨大です。私はmmapメモリのいくつかのチャンク、100 - 500メガバイトのそれぞれのプログラムを持っています。私は必然的に数回再マッピングすることになり、利用可能な連続スペースの断片化を引き起こす可能性があります。64ビットプロセスでは、私のmmap/malloc要求は拒否されますか?

スペースの断片化が発生しても、使用可能なアドレス空間に関しては、必ずしも小さくなることは間違いありません。

私の質問は次のとおりです。これらの制約を前提として、通常の状況では、すべてのmmapリクエストが成功すると期待できますか?彼らが失敗する理由は何でしょうか?

私は、ヒープがそれ自身に全体のスペースを持っていないことを知っていますが、それは大多数を持っていると思います。

Mac OS/Linux。

+2

ハードウェア障害。それはあなたに起こる可能性があります。 –

答えて

26

は、「64ビットオペレーティングシステム」のアドレス空間のサイズは必ずしも完全な64ビットの範囲をカバーしていないことに注意してください得ることができます。

例えば、実際に利用可能な仮想アドレス範囲は「唯一の」2x128TBです(つまり、64ビットx86、別名「AMD64」)。つまり、2つの分離した47ビットのチャンクで48ビットです。一部のSPARCシステムでは、2x2TBまたは2x8TB(41/44ビット)です。これは、MMUがこれらのプラットフォームで動作する方法によるものです。

これらのアーキテクチャ上の制限に加えて、オペレーティングシステムがアドレス空間をレイアウトする方法もここでは重要な役割を果たします。
64bit Windows on x64では、(64bitであっても)アプリケーションの仮想アドレスサイズを8TB(各カーネルとユーザ側で1)に制限しています。システム固有の制限内 - - setrlimitを介して調整する(Linux、MacOSXのと*のBSDを含む)UN * Xシステムで

は、一方がgetrlimit()介しを照会、及びできRLIMIT_ASあります。 ulimitコマンドで使用されます。プロセスが作成できるすべてのマッピング(mmap()またはmallocバックエンド、sbrk()経由)を含む、許可された仮想アドレス空間の上限を返す/設定します。 しかし、合計アドレス空間のサイズは、単一のマッピングの最大サイズと異なります。

これを考えると、64ビットLinuxでも仮想アドレス空間を使い果たすのは難しくありません。テストのために、mmap()に同じ500GBファイル、たとえば200回試してみてください。最終的にmmapは失敗します。要するに

:あなたは仮想アドレス空間の外にいる一度

  • mmap()は間違いなく失敗します。これは、仮想アドレスがであり、有効ビット数がであり、64ビットである可能性があるため、多くの「64ビット」アーキテクチャではやや驚くべきことに実現可能です。正確なカットオフはCPUとオペレーティングシステムによって異なり、上限はgetrlimit(RLIMIT_AS)で問い合わせるか、setrlimit(RLIMIT_AS)で設定します。
  • アドレス空間の断片化は、異なる順序で異なるサイズのブロックで頻繁にmmap()/munmap()を使用して64ビットで発生する可能性があります。これにより、最終的に単一のチャンクとしてマップできる最大サイズが制限されます。正確にこれが起こると予測するのは、あなたの "マッピング履歴"とオペレーティングシステムの仮想アドレス空間割り当てアルゴリズムの両方に依存するため、難しいです。 ASLR(アドレス空間レイアウトのランダム化)がOSによって実行されると、正確に予測できず、正確に再現できないことがあります。
  • malloc()も、オーバーコミットによりシステム内の物理容量(物理+スワップ)よりも多くのメモリを「尋ねる」ことを可能にするシステム(Linuxのような)ではVA限界に達するまでに失敗します。何のオーバーコミットが有効にされていないマシン/オペレーティング・システムで
  • マッピングのこれらのタイプは、実際のメモリまたはスワップによるバッキングストアを必要とするため、物理+スワップは、疲れているとき、MAP_ANONおよび/またはMAP_PRIVATEとの両方malloc()mmap()は失敗します。

リトルテクニカルアップデート:上記のx86およびsparcと同様に、新しいARMv8(64ビットARM、Linuxでは「AArch64」と呼ばれます)MMUには、64の「分割」アドレス空間/アドレスのビット数は、40個だけが適切です。 Linuxはユーザーのために39ビット、仮想アドレスは0 ...以降、カーネルは39ビット、仮想アドレスは... 0xFFFFFFFF.FFFFFFFFです。したがって、512GB(これは、アプリケーションがmmapを試している時点で既に使用されているものを除いています)です。
comments here(AArch64アーキテクチャイネーブラーカーネルパッチシリーズから)を参照してください。

+2

+1あなたの担当者はこのような素敵な答えで815以上になるはずです。 –

+0

断片化について私は32ビットシステム上のループでそれらをマッピングし、マッピング解除して、1から4 GBまでのサイズの32個のファイルすべてであなたが言ったことを試しました。 4.0GBのファイル1つを除いて、要求されたポインタのパラメータとしてNULLを渡しても、mmapは常に各ファイルの同じアドレスを再利用しました。 500GBのファイルが64ビットで表示されているだけですか? – Marenz

+1

'mmap'を介してアドレス空間のフラグメンテーションを作成するには、異なる順序で異なるサイズでmap/unmap操作を実行します。私。 mmap 1000ファイルにはそれぞれ1MB、3分の1をアンマップ、それぞれ2MBのmmap 150ファイル、そのうちのランダム20をアンマップする、...このようなことを言う。同じデータセット上のmmap/munmapの単純なループは断片化しません(非常にバグの多いASLRアルゴリズムが使用されている場合を除きます)。 mmap/munmap/mmapが同じアドレスを再利用するかどうかは、ASLRの実装に依存します(異なるPIDで同じプログラムを再起動すると、選択したアドレスが異なる場合があります)。 –

0

man mmapのエラーリストを確認するだけです。

+0

はい、しかし、ENOMEM(および他の1つまたは2つのもの)を除くすべてのものは避けられます。私は '/ ENOMEM'のようなものが起こるかもしれない理由を尋ねています。 – Joe

+2

プロセスが予約できる仮想メモリの量には制限があります。 'ulimit -v'を参照してください。 –

8

mmapおよびmallocは、物理メモリ(RAM +スワップ)が不足しているために失敗することがあります。一般に、Unixの標準では、「プロセスのアドレス空間に許されている」アドレス範囲が記述されています。それとは別に、

機能が 困難の場合に エラーコードを返すように宣伝された場合は、なたにもチェックしても、いや、 ためにそのコードをチェック あなたのコードのトリプルサイズと あなたのタイピング指で痛みを感じます。 もしあなたが「それは が私に起こることはありません」と思ったら、神は確かにあなたの傲慢さのためにあなたを罰するでしょう。

Spencer

+0

私はあなたがエラーをチェックしないとは思わないと思う! – Joe

+0

@ジョー:あなたがチェックしている良いこと。しかし、なぜ、あなたはこれを求めているのですか? –

+0

私はそれが起こる可能性が高いかどうか、もしそうなら、どのような状況であるかを知りたいからです。 – Joe

0

まあ、OS/Cライブラリには、十分なメモリがあるかどうかを判断して自由です。どのように決定するのかは分かりません(明らかにOS特有のもので、調整可能なものもあります)。しかし、ある時点でOSは「これ以上」とは言えません。

可能なメモリを割り当てるために失敗の理由:

  • Linuxはovercommitメモリだろうが、これは調整可能です。設定方法によっては、RAM +スワップを超えた直後にENOMEMを取得することがあります。
  • メモリ制限がulimitを使用して設定されている場合は、ENOMEMでも早く
+0

堅牢なサーバー、ワークステーション、またはリアルタイム使用のために適切に構成されたLinuxシステムは、オーバーコミットを無効にします。オーバーコミットを有効にしてLinuxを実行すると、Windows 95を実行するのと同じようになります... –

+0

@R:まあ、思い出した限り、Linuxではオーバーコミットがデフォルトでオンになっています。したがって、かなりの数のサーバーがそれを実行します。もちろん問題になることもあります。 – sleske

+0

私はそれがデフォルトでオンであることを知っています。しかし、もし私がLinux管理者を雇っていたら、彼らが過間勘定が何であるか、そしてそれを止める方法を知っていることを確認することは、私の最初のインタビューの質問の1つになります。 :-) –