ただし、次のとおりです。
- リクエストするサイズはページ サイズの倍数です
- 私が要求する開始アドレスは、サイズ + 最後の割り当ての開始アドレスです
mmap を使用してヒープにメモリを割り当てるときに常にこれらの規則に従うと、返されるアドレスは連続しますか? それとも、それらの間にギャップがある可能性がありますか?
ただし、次のとおりです。
mmap を使用してヒープにメモリを割り当てるときに常にこれらの規則に従うと、返されるアドレスは連続しますか? それとも、それらの間にギャップがある可能性がありますか?
MAP_FIXED フラグを使用すると、必要な動作を得ることができます。残念ながら、あなたの目標では、それは普遍的にサポートされていないため、戻り値をチェックして、要求した割り当てが得られたことを確認する必要があります. 移植性を高めるには、呼び出しが 0 を返したときのバックアップ プランが必要です。
クイックアンサー: 必ずしもそうではありません。さまざまなマシンでの限られた広範なテストの両方で「ほぼ常に機能する」可能性は十分にありますが、それは間違いなく良い習慣ではありません。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() を呼び出すことによって作成および管理されます。
これは指定されていないと思いますが、いわゆる「実装の詳細」です。つまり、どちらか一方の動作に依存するべきではありませんが、ポインターは不透明であり、その正確な値には関心がないと想定してください。
(とは言っても、ハッキングの場所と時間が存在する可能性があります。その場合、OS の動作を正確に把握する必要があります。)