2

ただし、次のとおりです。

  • リクエストするサイズはページ サイズの倍数です
  • 私が要求する開始アドレスは、サイズ + 最後の割り当ての開始アドレスです

mmap を使用してヒープにメモリを割り当てるときに常にこれらの規則に従うと、返されるアドレスは連続しますか? それとも、それらの間にギャップがある可能性がありますか?

4

3 に答える 3

3

MAP_FIXED フラグを使用すると、必要な動作を得ることができます。残念ながら、あなたの目標では、それは普遍的にサポートされていないため、戻り値をチェックして、要求した割り当てが得られたことを確認する必要があります. 移植性を高めるには、呼び出しが 0 を返したときのバックアップ プランが必要です。

于 2012-11-05T15:02:11.633 に答える
2

クイックアンサー: 必ずしもそうではありません。さまざまなマシンでの限られた広範なテストの両方で「ほぼ常に機能する」可能性は十分にありますが、それは間違いなく良い習慣ではありません。MAP_FIXED フラグはほとんどの Linux でサポートされていますが、私の経験ではバグもあります。避ける。

あなたの場合は、必要なものをすべて一度に割り当ててから、マッピングの各サブセクションに手動でポインターを割り当てることをお勧めします。

int LengthOf_FirstThing = 0x18000;
int LengthOf_SecondThing = 0x10100;
int LengthOf_ThirdThing = 0x20000;

int _pagesize = getpagesize();
int _pagemask = _pagesize - 1;

size_t sizeOfEverything = LengthOf_FirstThing + LengthOf_SecondThing + LengthOf_ThirdThing;
sizeOfEverything = (sizeOfEverything + _pagemask) & ~(_pagemask);

int8_t* result = (int8_t*)mmap(nullptr, sizeOfEverything, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
int8_t* myFirstThing = result;
int8_t* mySecondThing = myFirstThing + LengthOf_FirstThing;
int8_t* myThirdThing = mySecondThing + LengthOf_SecondThing;

このアプローチの利点は、マッピングしているそれぞれのものをページ サイズに厳密に合わせる必要がないことです。そして最も重要なことは、完全に連続したメモリを保証することです。

より長い回答: mmap() の実装では、「ヒント」アドレスを完全に無視できるため、アドレスが尊重されるとは決して期待しないでください。一部の実装では、新しい mmap() のページサイズの粒度が実際にはサポートされていない可能性があるため、これは予想よりも一般的である可能性があります。非常に大きな仮想アドレス空間を管理するために必要なオーバーヘッドを削減するために、有効な開始マップを 16k または 64k の境界に制限する場合があります。そのような実装は、そのような境界に揃えられていない mmap() ヒントを常に無視します。

さらに、mmap() はヒープからメモリをまったく割り当てません。ヒープは、プロセスの作成時に C ランタイム ライブラリ (*nix の glibc) によって作成/予約されるメモリ領域です。通常、malloc() と new/delete は、malloc/new を内部で使用する可能性のあるライブラリと共に、ヒープからプルする唯一の関数です。ヒープ自体は通常、内部で mmap() を呼び出すことによって作成および管理されます。

于 2012-12-23T22:34:35.650 に答える
1

これは指定されていないと思いますが、いわゆる「実装の詳細」です。つまり、どちらか一方の動作に依存するべきではありませんが、ポインターは不透明であり、その正確な値には関心がないと想定してください。

(とは言っても、ハッキングの場所と時間が存在する可能性があります。その場合、OS の動作を正確に把握する必要があります。)

于 2012-11-05T15:00:12.110 に答える