ファイル長より大きいアドレスを読み書きするときのファイルサポートメモリマッピングの動作は何ですか?

ファイル長より大きいアドレスを読み書きするときのファイルサポートメモリマッピングの動作は何ですか?

長さが非常に長いファイルのメモリマップを開くことが未定義の動作であることを確認したいと思います。マイユースケースは、システムコールwriteを介してファイルを追加するときですmremapmmapたとえば、大きすぎる場合、またはページの境界に揃っていない場合)"の場合はEINVALを返しますが、これは明らかに非常に不明です。よりはるかに大きいメモリマップを開き、ここに値を書き込んでからすぐにその値を読み取るプログラムを書くと、呼び出しがエラーを返さずに値mmapが実際に正しく書き込まれることがわかりました。問題がある値を破損したものとしてマークする以外に、何もしない小さなインラインアセンブリを使用して、このロードとストアを最適化しないようにしましたSIGBUS。 、私の知る限りではない。

これはmmap、この方法を使用すると、メモリマップを再生成せずにファイルの変更を追跡するユースケースで機能できることを意味しますが、これが意図的なものか偶発的なのかを疑問に思います。私はLinuxカーネルの保証されていない動作に頼りたくありません。特に、情報がディスクと正しく同期されておらず、後で重大なエラーが発生する可能性がある場合は、これがさらに重要です。この動作はどこかに定義または保証されていますか?

答え1

答えは(隠されている)mmap(2) ページの NOTES 部分:

   A file is mapped in multiples of the page size.  For a  file  that
   is not a multiple of the page size, the remaining memory is zeroed
   when mapped, and writes to that region are not written out to  the
   file.

しかし、テキストはもう少し明確になり、ページの議論はSIGBUSまったく明確ではありません。私は持っています変更上記のテキストは次のようになります。

   A  file  is mapped in multiples of the page size.  For a file that
   is not a multiple of the page size, the  remaining  bytes  in  the
   partial page at the end of the mapping are zeroed when mapped, and
   modifications to that region are not written out to the file.

説明を次のように変更しましたSIGBUS

   SIGBUS Attempted  access  to a page of the buffer that lies beyond
          the end of the mapped file.   For  an  explanation  of  the
          treatment  of the bytes in the page that corresponds to the
          end of a mapped file that is not a  multiple  of  the  page
          size, see NOTES.

答え2

アクションが指定されましたが、指定されていません。Linuxmmapのマンページ、かなりPOSIXでは:

システムは常にオブジェクトの末尾にある部分ページをゼロで埋める必要があります。さらに、システムはオブジェクトの最後のページの終わり以降に変更を記録しません。開始アドレス範囲内の参照お父さんそして続けてロンドンページ全体のオブジェクトの終わり以降のバイトは、SIGBUS信号が送信されるようにします。

ファイルmmapMAP_SHAREDマッピングがファイルサイズより大きく、ファイルの終わりを超えてメモリに書き込もうとした場合はいSIGBUSマッピング自体に範囲が含まれている場合でも、これが表示されることが/proc/.../mapsあります(確認)。上記のテキストでは、お父さんは返されたアドレスmmapなので、仕様によれば、マッピングされたメモリ領域内にあるが、マッピングされたオブジェクトの終わりから完全に外れたページのアドレスにアクセスすると、部分的に内部SIGBUSのページで読み書きが行われます。通常、メモリ管理デバイスによって提供される保護に対応するマッピングされたオブジェクト。

さらに、ユースケースに必要な動作は定義されていません。

呼び出し後にマップされたファイルのサイズが変更された場合マッピング()マッピングされたファイルに対する他の操作の結果として、ファイルの追加または削除された部分に対応するマッピングされた領域部分への参照の効果は指定されません。

Linuxのページキャッシュに関連するいくつかの微妙な部分があります(参照:マニュアルページのエラーセクション)、これは上記の内容に加えて驚くべき動作を引き起こす可能性があります。ファイルの終わりを超えて、マップの最後のページ内に書き込まれたデータはファイルに書き込まれませんが、後続のマッピングまで保持できます。

mmapEINVAL指定された値が通常有効でなく、マッピングされているファイルと特定の関係がない場合は、ファイルをマッピングすると次のようになります。つまりソート要件が満たされていない場合、またはオフセットと長さがカーネルが管理できる最大ファイルサイズと互換性がない場合。

関連情報