ファイルの非線形部分をプロセス空間で線形にマッピングする必要があるシナリオがあります。
たとえば、ファイルが 10 ページの場合、最初の 3 をマップし、4 をスキップし、最後の 3 をマップする必要があるかもしれません。マッピングは線形である必要があります。 4、5、6、7 はマッピングされませんでした。
Linuxでこれが可能かどうか知りたいです。
ありがとう。
ファイルの非線形部分をプロセス空間で線形にマッピングする必要があるシナリオがあります。
たとえば、ファイルが 10 ページの場合、最初の 3 をマップし、4 をスキップし、最後の 3 をマップする必要があるかもしれません。マッピングは線形である必要があります。 4、5、6、7 はマッピングされませんでした。
Linuxでこれが可能かどうか知りたいです。
ありがとう。
mmap()
2 回目以降のマッピングの固定アドレスを指定するために使用して複数回呼び出す戦略はMAP_FIXED
機能するはずですが、問題は、最初のマッピングの直後にメモリに既にマップされているものがある場合、それが上書きされることですMAP_FIXED
。新しいマッピングを作成する前にそこにありました。
ここで Linux システムのアドレス空間のいくつかのマッピングのレイアウトを調べたところ、少なくとも時々、メモリ マッピング用にカーネルによって選択されたアドレスが上位アドレスから下位アドレスへと下向きに成長することが観察されました。住所。つまり、新しいマッピングには、最新の既存のマッピングで使用されたアドレス空間のすぐ下のアドレス空間が与えられます。その戦略の下では、最初のマッピングを作成するときに、そのマッピングの直後のアドレス空間がすでに別のものによって占有されていることが事実上保証されます (システム ライブラリなど、おそらく重要なものでもあります)。他のシステム (異なるカーネル バージョン、異なるアーキテクチャ、または非 Linux など) では、この問題を起こりにくくしない別のアドレス空間割り当て戦略を使用する場合があります。
最初に、構築するすべてのマッピングのサイズの合計であるダミー マッピングを作成します。したがって、ファイルの最初の 3 ページをマップする場合は、4 ページをスキップして、さらに 3 ページをマップし、6 ページのダミー マップを作成します。
このダミー マッピングでは、匿名メモリをマップするだけです ( MAP_ANONYMOUS
)。このマッピングにも使用することを提案してくれたBasile Starynkevitchに感謝します。MAP_NORESERVE
このダミー マッピングを、実際に必要なファイルのマッピングに 1 つずつ置き換えますMAP_FIXED
。各マッピングを表示する正確なアドレスを指定するために使用します。
編集:munmap()
私は当初、新しいマッピングにアドレス空間を再利用する前にダミー マッピングを破棄することを提案しましたが、これは不要であることを指摘してくれたjstineに感謝します (また、プログラムがマルチスレッド化されている場合は競合状態が発生します)。
最初のマッピングでは、ダミー マッピングによる開始アドレスを使用します。2 番目のマッピングのアドレスは、ダミー マッピングの開始アドレスに最初のマッピングのサイズを加えたものとして計算します。これにより、最初のマッピングの直後に 2 番目のマッピングが配置されます。3 番目と 4 番目のマッピングについても同様です。あなたのシナリオでは、すべてがページサイズでページに揃えられているため、配置によるギャップはありません。
手順 2 ですべてのマッピングを作成した後、元のダミー マッピングは何も残っていないはずです。
Celada による以前の回答に加えて、 mmap(2)の後の Linux 固有のremap_file_pages(2) syscall にも興味があるかもしれません。
そして最初のものは、スワップ空間の消費を避けるためにmmap
使用するかもしれませんMAP_NORESERVE
(そして、データではなくアドレス空間を予約するだけです)。