kawasin73 / knowledge

気になったツールやサイト、勉強した内容をまとめます。
8 stars 0 forks source link

Mmap:msync と fsync の関係 #17

Closed kawasin73 closed 5 years ago

kawasin73 commented 5 years ago

Go 言語では、syscall パッケージに syscall.Mmap()syscall.Munmap() が用意されているが、msync に相当するインターフェイスは用意されていない。

一方、Mmap を実行する時にはファイルディスクリプタが必要になるが、ファイルディスクリプタを提供する os.File 構造体は Sync() インターフェイスを用意しており、内部で fsync システムコールを実行している。

mmap した内容がディスクに書き込まれたことを保証するために、fsync を利用することができるかどうかを調査する。

kawasin73 commented 5 years ago

fsync()msync() の違い

mmap の共有ファイルマッピングでは、複数のプロセスで同じページキャッシュを利用するが、Linux の場合通常のファイルIOで使われるページキャッシュを利用する。

現代の多くのUNIXシステム同様に Linux でも統合仮想メモリとでも言えるメモリ管理方式を実装しています。この方式では、可能ならば、メモリマッピングとバッファキャッシュは物理メモリの同じページを共有します。すなわち、マッピングにおるファイル内容の参照と I/O システムコールによるファイル内容の参照(read()write()など)は常に一意であり、msync() の意味はマッピングをディスクへ強制的に書き出すことしかありません。

「LINUXプログラミングインターフェース」より p.1090「49.5 マッピング領域とファイルの同期:msync()」

そのため Linux では、fsync() を呼び出すことで mmap のマッピングをディスクに書き込むことができる。

ファイルIOで使われるページキャッシュと異なるシステムの場合は、msync()MS_SYNC オプションで呼び出すか、msync()MS_ASYNC で呼び出した(マッピングとカーネルのバッファキャッシュを同期させる)後に、fsync() を呼び出すことでディスクへ書き込むことができる。

また munmap()close() では、ディスクへの書き込み完了は保障されないため、msync() または、fsync() を呼び出す必要がある。

また、fsync() は、変更された部分のページをディスクデバイスへ書き込むため、msync() と挙動が同じになる。

fsync() は、ファイルディスクリプター fd で参照されるファイルの、メモリー内で存在す る修正されたデータ (つまり修正されたバッファーキャッシュページ) を、ディスクデ バイス(またはその他の永続ストレージデバイス) に転送 (「フラッシュ」) し、これ により、システムがクラッシュしたり、再起動された後も、変更された全ての情報が 取り出せるようになる。 https://linuxjm.osdn.jp/html/LDP_man-pages/man2/fsync.2.html