2

ファイルをメモリ マップし、そこに含まれるデータの型変換を透過的に実行できるシステムを考えています。2番目のメモリ領域をmmapして保護し、新しいページがアクセスされたときにsegfaultをキャッチすることで、メモリアクセスをキャッチできるようです。これにより、必要な読み取り時の型変換を処理できます。

ただし、読み取り/書き込みの互換性を保つには、OS がメモリの一部をディスクにページングしているときにキャッチする方法が必要です。これにより、書き込み前に別の方法で型変換を行うことができます。

この方法でページング システムをフックする機能はありますか?

4

2 に答える 2

3

あなたが望んでいることは不可能であり、 の根本的な誤解を反映していmmapます。ファイルに裏打ちされたマップがディスクに書き戻されるイベントは関係ありません。これが発生するまで、ファイルを読み取ろうとする試みはすべて ( POSIX に準拠するために必要)、ページの変更されたメモリ内コピーから読み取られるためです。ディスク上の古いコンテンツではありません。言い換えると、変更されたページのディスクへの書き戻しはアプリケーションに対して完全に透過的であり、電源が失われたり再起動したりしないと仮定すると、変更されたページがディスクに書き戻されない可能性は十分にあります。

あなたのデザインは機能しません。この種の動作が必要な場合は、別のことを行う必要があります。

于 2012-07-25T18:08:28.033 に答える
2

メモリ マップと SIGSEGV ハンドラの使用には少し問題があります。まず、mprotect()async-signal safeではありません。つまりmprotect()、シグナル ハンドラーでの動作は保証されていません。次に、シグナル ハンドラと複数のスレッド間で必要な構造の同期は非常に複雑です (ただし、GCC __syncおよび/または__atomicビルトインを使用すると可能です)。シグナル ハンドラで標準のロック プリミティブを使用できないためです。幸いなことに、単純にシグナルハンドラから戻ります。カーネルは問題のある命令をスキップしないため、直後に同じシグナルが発生します。

私は匿名のプライベート未予約メモリ マップをテストするための小さなプログラムを作成し、マップを使用read()write()て更新しました。問題は、シグナル ハンドラがマップを更新している間に、他のスレッドがマップにアクセスする可能性があることです。

現在アクティブな領域に一時ファイルを使用し、レコードがページ境界をまたぐときに部分的なレコードを保持するために前後に追加のページを使用すると、うまくいくと思います。

実際のデータ ファイルは、非公開の匿名で予約されていない、アクセスできないマップ ( PROT_NONEMAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE) で表されます。SIGSEGV シグナル ハンドラーは、そのマップへのアクセスをキャッチします。そのマップのページに位置合わせされた領域がマップ解除され、一時ファイル ( MAP_SHARED | MAP_FIXED | MAP_NORESERVE) からマップされます。秘訣は、一時ファイルMAP_SHARED | MAP_NORESERVEを別のメモリ領域に追加でマップ ( ) できることです。シグナル ハンドラは、マップ内の一時ファイルのマップを解除するだけで、変換中に他のスレッドが領域にアクセスするのを停止できます。データは、別のメモリ領域のライブラリ関数で引き続き使用できます (実際のデータ ファイルを使用read()して読み書きできます)。(ページキャッシュからの)まったく同じページが使用されることを意味し、カーネルがそれらのためにスワップまたはRAMを予約しないことを意味します。write()MAP_SHAREDMAP_NORESERVE

このアプローチは、スレッドとロックに関してはうまく機能するはずですが、非同期シグナルセーフではないmmap()munmap()、およびという問題が依然としてあります。mremap()ただし、アトミックにのみアクセスされるグローバル変数があり、アプリケーション/ライブラリコードが構造体やマップを変更している場合にシグナルハンドラーがすぐに戻る場合、これは信頼できるはずです。

于 2012-07-26T12:41:16.273 に答える