6

連続していないファイルのブロックを連続したメモリにマッピングすることに関する質問への回答では、ここで、最後の (lpBaseAddress) パラメーターの「安全な」値を確立するために、MEM_RESERVE でVirtualAllocEx () を使用する必要があることを、ある回答者から提案されました。 MapViewOfFileEx ()の場合。

さらに調査した結果、このアプローチにより MapViewofFileEx() がエラー 487:「無効なアドレスにアクセスしようとしています」で失敗することが判明しました。 MSDNページには次のように書かれています

「VirtualAllocまたはVirtualAllocEx関数を使用してメモリを予約するなど、マッピングに使用される領域で他のメモリ割り当てを行うことはできません。」

ドキュメントは有効な一連の呼び出しに関してあいまいであると考えられるかもしれませんが、実験では、VirtualAllocEx() を使用して MapViewOfFileEx() 用にメモリを予約することは有効ではないことが示唆されています。

ウェブ上で、値がハードコードされた例を見つけました - example :

#define BASE_MEM     (VOID*)0x01000000

...

hMap = MapViewOfFileEx( hFile, FILE_MAP_WRITE, 0, 0, 0, BASE_MEM );

私には、これは不十分で信頼性がないように思えます...なぜこのアドレスが安全なのか、またはそこに安全にマップできるブロックの数ははっきりしていません。他の割り当てのコンテキストで機能するソリューションが必要であり、ソースをコンパイルして 32 ビットと 64 ビットの両方のコンテキストで動作させる必要があることを考えると、さらに不安定に思えます。

私が知りたいのは、アドレス空間のプールを確実に予約して、後で MapViewOfFileEx が確実に使用してブロックを明示的なメモリ アドレスにマップできるようにする方法があるかどうかです。

4

3 に答える 3

0

ベース アドレスを指定すると、関数はそのアドレスにファイルをマップしようとします。そのベース アドレスを使用できない場合 (要求されたメモリ領域のすべてまたは一部が既に使用されているため)、呼び出しは失敗します。

ほとんどのアプリケーションでは、自分でアドレスを修正しようとしても意味がありません。あなたが洗練されたデータベース プロセスであり、効率上の理由から既知の構成を持つマシン上で独自のメモリ レイアウトを慎重に管理しようとしている場合、それは合理的かもしれません。しかし、失敗に備える必要があります。

64 ビット プロセスでは、仮想アドレス空間がかなり広く開かれているため、ある程度確実にベース アドレスを選択することは可能かもしれませんが、気にする必要はないと思います。

MSDNから:

現在安全な (オペレーティング システムで使用されていない) アドレスを指定することはできますが、そのアドレスが長期にわたって安全であるという保証はありません。したがって、オペレーティング システムにアドレスを選択させることをお勧めします。

「時間の経過とともに」とは、OSの将来のバージョンと、使用しているランタイムライブラリ(メモリ割り当てなど)を指していると思います。これは、メモリレイアウトに対して異なるアプローチをとる可能性があります。

また:

lpBaseAddress パラメーターでベース オフセットが指定されている場合、指定されたメモリ領域が呼び出し元のプロセスによって使用されていなければ、関数は成功します。システムは、同じメモリ領域が他の 32 ビット プロセスのメモリ マップ ファイルに使用できることを保証しません。

基本的に、あなたの本能は正しいです。ベースアドレスを指定することは信頼できません。試すことはできますが、失敗に備える必要があります。

あなたの質問に直接答えるには:

私が知りたいのは、アドレス空間のプールを確実に予約して、後で MapViewOfFileEx が確実に使用してブロックを明示的なメモリ アドレスにマップできるようにする方法があるかどうかです。

いいえ、ありません。ランタイム環境に多くの制約を適用しないわけにはいきません (たとえば、特定のバージョンの OS に制限する、すべての DLL にベース アドレスを設定する、DLL インジェクションを許可しないなど)。

于 2012-08-25T15:59:11.590 に答える
0

あなたがやろうとしていることは不可能です。

MapViewOfFileEx docsから、指定するポインターは「マッピングが開始される呼び出しプロセスのアドレス空間内のメモリーアドレスへのポインターです。これは、システムのメモリー割り当ての粒度の倍数である必要があります。そうしないと、関数が失敗します。」

メモリ割り当ての粒度は 64Kであるため、ファイルの異なる 4K ページを仮想メモリ内の隣接する 4K ページにマップすることはできません。

于 2012-08-25T18:38:43.730 に答える