mmapについて

参考: http://www.ncad.co.jp/~komata/c-kouza20.htm https://www.it-swarm-ja.tech/ja/c/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%ABmmap%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8B%E3%81%AE%E3%81%AF%E3%81%84%E3%81%A4%E3%81%A7%E3%81%99%E3%81%8B%EF%BC%9F/958534019/#:~:text=mmap%20%E3%81%AB%E3%81%AF%E3%80%81%E5%A4%A7%E3%81%8D%E3%81%AA%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB,%E3%81%AB%E3%81%AA%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82

概要

※とりあえず参考リンクから多くを引用している※

mmapはファイルをメモリにマッピングするものです。わかりやすく言うと、UNIXのOSが行なっているページングやスワッピングを自プロセスで行なうようなものです。 これを使うメリットとしては、メモリ確保サイズが確保開始時に決定できない場合、簡単にはmalloc()で適当な量を確保し、足りなければrealloc()を使用して拡大することになりますが、 realloc()を繰り返すとメモリ領域中に空きが出来やすく、大規模なシステムでは実際使用しているメモリより空き空間の方が数倍大きくなってしまい、 メモリ不足で実行不可能になる場合があります。 mmapを使用すれば、別々に拡大していくような管理が可能なので、また、スワップスペースとは別の位置に置くことにより、 多数の動的メモリを必要とする場合に安全に動作することが可能になる場合があります。 ただし、基本的にファイルなので、最大ファイルオープン可能数を越えてマッピングすることは出来ませんので、環境の調査・調整はしっかり行なわなければなりません。 また、mmapは可能な範囲でRAM上に展開しながら動作してくれるので比較的高速ですが、巨大な領域を移動する場合には当然ページングなどと同様に遅くなります。 その他に、メモリイメージをファイルとして扱えますので、単純なメモリイメージの保存・再利用も可能ですし、更に共有メモリの用にメモリイメージを共有することも可能です。

  • ファイルをメモリにマッピングする

  • malloc系でチマチマメモリ領域を獲得すると空きが出やすくなったりするがそれがない

  • fdの数に注意しないといけない.

  • 巨大な領域の移動は当然ページングのように遅くなる

  • 同じファイルの読み取りを複数のプロセスが行うような場合はmmapで同じ物理メモリページを共有してできるのが良い.

  • mallocと比較して,スワップの時にバッファに書き込む必要がない.ファイルからの復元ができれば良いだけだから.

  • mmapは連続したアドレス空間が必要だから,アドレス空間が小さかったりすると(32bitマシンだと)ファイルサイズを気を付ける場面が出てくる.

  • mmapはページサイズのオフセットでマッピングを開始する必要がある

  • mmapはパイプやttyには利用できない

  • ファイルサイズが十分小さい(16K未満?)と遅いらしい.read()とかと比べて. これは、タイムスライス内でカーネルが読み取りを完全に満たすことがあり、コードが切り替わらないことがあるためです。 ページフォールトでは、別のプログラムがスケジュールされる可能性が高くなり、ファイル操作の待ち時間が長くなります。

  • mmapは大きいファイルにランダムアクセスする際に有用.

  • mmapはバッファリングに煩わされることなく,メモリ操作(memcpy・ポインター演算)でアクセスできる

mmap, munmap - map or unmap files or devices into memory ってことはデバイス(のメモリ空間)もmapできるんか

以下Linuxシステムプログラミングから

mmap( )の利点 mmap( )を介したファイルの操作には、標準のread( )およびwrite( )システムコールに比べていくつかの利点があります。

  • メモリマップファイルの読み取りと書き込みにより、read( )またはwrite( )システムコールを使用するときに発生する余分なコピーを回避します。この場合、データはユーザースペースバッファーとの間でコピーする必要があります。

  • 潜在的なページフォールトは別として、メモリマップトファイルの読み取りと書き込みでは、システムコールやコンテキストスイッチのオーバーヘッドは発生しません。メモリにアクセスするのと同じくらい簡単です。

  • 複数のプロセスが同じオブジェクトをメモリにマップすると、データはすべてのプロセス間で共有されます。読み取り専用および共有の書き込み可能なマッピングは完全に共有されます。書き込み可能なプライベートマッピングには、まだCOW(コピーオンライト)ページが共有されています。

  • マッピングを探索するには、簡単なポインター操作が必要です。 lseek( )システムコールは不要です。

これらの理由から、mmap( )は多くのアプリケーションにとって賢明な選択です。

mmap( )の欠点 mmap( )を使用する際に留意すべき点がいくつかあります。

  • メモリマッピングは常に整数のページ数です。したがって、バッキングファイルのサイズと整数のページ数の差は、スラックスペースとして「無駄」になります。小さなファイルの場合、マッピングのかなりの割合が無駄になる可能性があります。たとえば、4 KBページでは、7バイトのマッピングは4,089バイトを無駄にします。

  • メモリマッピングは、プロセスのアドレス空間に収まる必要があります。 32ビットのアドレス空間では、非常に多数のさまざまなサイズのマッピングにより、アドレス空間が断片化され、大きな空きの連続した領域を見つけることが難しくなります。もちろん、この問題は64ビットのアドレス空間ではそれほど顕著ではありません。

  • カーネル内のメモリマッピングおよび関連するデータ構造の作成と保守にはオーバーヘッドがあります。このオーバーヘッドは、特に大きく頻繁にアクセスされるファイルの場合は特に、前のセクションで説明した二重コピーを削除することで一般的に不要になります。

これらの理由から、mmap( )の利点は、マップされたファイルが大きい場合(したがって、無駄なスペースがマッピング全体のわずかな割合である場合)、またはマップされたファイルの合計サイズが均等に割り切れる場合に最も大きく実現されますページサイズによって(したがって、無駄なスペースはありません)。

pipeとの比較についても書く必要がありそう

aaaaaaaaaaaaaaaaaa

man

#include<sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);