3

mmap 関数を使用してファイルをメモリにマップしたいと考えており、現在のプラットフォームの仮想メモリの量が巨大なファイルをマップするのに十分かどうかを知りたいです。32 システムの場合、4 Gb を超えるファイルをマップできません。アドレス可能なメモリの量を教えてくれますか、それともテストする必要がある他の型 (off_t など) はありますか
?std::numeric_limits<size_t>::max()

Lie Ryan がコメントで指摘しているように、ここでの「仮想メモリ」は悪用されています。ただし、問題は次のとおりです。ポインターに関連付けられた型があり、システムで対処できる上限を定義する最大値があります。このタイプは何ですか?size_t ですか、それとも ptrdiff_t ですか?

4

5 に答える 5

1

つまり、ポインターのサイズは、その「アドレス空間」が実際にどれだけ利用できるか、つまり、単一の連続したチャンクとしてマップできるかについては何もわかりません。

次の制限があります。

  • オペレーティング システム。理論的に可能なアドレス範囲のサブセットのみを使用可能にすることを選択する場合があります。これは、マッピング可能なメモリが OS 独自の目的 (たとえば、グラフィックス カードのフレーム バッファーを表示するため、そしてもちろん OS 自体で使用するため) に必要なためです。 )。
  • 設定可能な制限。Linux / UNIX では、「ulimit」コマンドそれぞれ。setrlimit() システム コールを使用すると、アプリケーションのアドレス空間の最大サイズをさまざまな方法で制限できます。Windows には、レジストリ パラメータによる同様のオプションがあります。
  • アプリケーションの履歴。アプリケーションがメモリ マッピングを広範囲に使用する場合、アドレス空間がフラグメント化され、「使用可能な」連続した仮想アドレスの最大サイズが制限される可能性があります。
  • ハードウェア プラットフォーム。一部の CPU には「穴」のあるアドレス空間があります。その例は 64 ビット x86 で、ポインターは 0x0..0x7ffffffffff または 0xffff000000000000 と 0xffffffffffffffff の間にある場合にのみ有効です。つまり、完全な 16EB の代わりに 2x128TB があります。48ビットの「署名付き」ポインターと考えてください...

最後に、「利用可能なメモリ」と「利用可能なアドレス空間」を混同しないでください。malloc(someBigSize) と mmap(..., someBigSize, ...) の実行には違いがあります。前者は要求に対応するために物理メモリの可用性を必要とする可能性があるのに対し、後者は通常、十分な大きさの空き領域の可用性のみを必要とするためです。アドレス範囲。

UNIX プラットフォームの場合、答えの一部は getrlimit(RLIMIT_AS) を使用することです。これにより、アプリケーションの現在の呼び出しの上限が得られます。前述のように、ユーザーおよび/または管理者がこれを構成できます。それより大きい領域を mmap しようとすると失敗することが保証されています。

于 2010-11-18T16:22:11.167 に答える
1

あなたの言い換えられた質問「システムで対処できる上限」については、やや誤解を招く可能性があります。これはハードウェア アーキテクチャ固有です。MMU が (uintptr_t)(-1) を有効なアドレスとして喜んで許可する 64 ビット アーキテクチャ (x64、sparc) があります。つまり、何かを 64 ビット アドレス空間の最後のページにマップできます。オペレーティングシステムがアプリケーションに許可するかどうかは、まったく別の問題です...

ユーザー アプリケーションの場合、「ハイ マーク」は (常に) アプリオリに固定されているわけではありません。たとえば、Solaris や Linux で調整可能です。そこで getrlimit(RLIMIT_AS) の出番です。

繰り返しになりますが、仕様上、(奇妙な) オペレーティング システムの設計が選択することを妨げるものは何もないことに注意してください。たとえば、アプリケーション スタックとヒープを「低い」アドレスに配置し、コードを「高い」アドレスに配置する、アドレス空間の穴があるプラットフォームで. そこには完全な 64 ビット ポインターが必要であり、それ以上小さくすることはできませんが、アプリで決して利用できない「アクセスできない / 無効な」範囲が任意の数存在する可能性があります。

于 2010-11-18T16:30:08.397 に答える
1

こんにちは、win32 でコーディングする場合は、GlobalMemoryStatusEx と VirtualQueryEx を使用できます。

于 2010-11-18T13:19:30.473 に答える
1

size_t可能な限り最大の単一の連続オブジェクトを格納するのに十分な大きさが必要です。これは、アドレス空間のサイズと同じではない場合があります (たとえば、セグメント化されたメモリ モデルを使用するシステムの場合)

ただし、フラットなメモリ空間を備えた一般的なプラットフォームでは、この 2 つは同等であるためsize_t、ターゲット CPU がわかっている場合は、実際に使用しても問題ありません。

とにかく、これは本当に有用なことを教えてくれません。確かに、32 ビットの CPU には 4GB のメモリ空間size_tがあり、32 ビットの符号なし整数も同様です。しかし、それはあなたがどれだけ割り当てることができるかについては何も言いません. メモリ空間の一部は OS によって使用されます。また、いくつかの部分は、独自のアプリケーションで既に使用されています: 実行可能ファイルをメモリ (およびそれが使用する可能性のある動的ライブラリ) にマッピングするため、各スレッドのスタック、ヒープに割り当てられたメモリなど。

いいえ、サイズを取得するなどのトリックは、size_t実行しているアドレス空間について少し教えてくれますが、あまり使用できるものはありません. プロセスやその他のメトリックで使用されているメモリの量を OS に問い合わせることができますが、これもあまり役に立ちません。プロセスが数メガバイトを使用することは可能ですが、それが非常に多くの小さな割り当てに分散しているため、たとえば 100MB を超える連続したメモリ ブロックを見つけることができません。そのため、32 ビット マシンでは、プロセスがほとんどメモリを使用しないため、このような割り当てを行うことはまずありません。(そして、OS に魔法のWhatIsTheLargestPossibleMemoryAllocationICanMake()API があったとしても、それは役に立ちません。それは、直前に必要だっものを教えてくれるでしょう。. ファイルをマップしようとした時点で、回答がまだ有効であるという保証はありません。

したがって、実際にできる最善の方法は、ファイルをマップしてみて、失敗するかどうかを確認することです。

于 2010-11-18T13:53:27.827 に答える
0

試すことができsizeof(int*)ます。これにより、ターゲット プラットフォーム上のポインターの長さ (バイト単位) が得られます。したがって、アドレス可能なスペースの大きさを知ることができます。

于 2010-11-18T13:18:05.453 に答える