0

メモリ マッピングを使用してファイルを開く予定です。

ファイルは同じ方法で別のプロセスによって既に開かれています。つまり、独自のメモリ マップ ビューが開かれており、時々ファイルが編集されます。

同じファイルを自分で編集し、他のプロセスが行った変更を上書きして競合することなく、他のプロセスとできるだけ効果的にアクセスを共有したいと考えています。

まず、ファイルを直接開くことができます。

IntPtr f_ptr = CreateFile(
 path,
 GENERIC_READ | GENERIC_WRITE,
 FILE_SHARE_READ | FILE_SHARE_WRITE,
 IntPtr.Zero,
 OPEN_ALWAYS,
 FILE_FLAG_RANDOM_ACCESS,
 IntPtr.Zero);

ただし、ファイル バイナリを直接編集することは、他のプロセスのメモリ マッピング オブジェクトが私の変更を上書きする可能性があるという点で効果的ではありません。

以下のように、独自のファイル マッピングと独自のビューを開くと、他のプロセスが自動的に更新され、編集内容が上書きされないように見えます。

ここで起こっているシンクロニシティは何ですか?

他のプロセスのファイル マッピングにマップされた独自のビューを開いているわけではありません。同じファイルにまったく新しい FileMapping を作成しました。

ファイルシステムまたは FileMapping システムは、これを何らかの形で理解しているようです。なんで?

// file map pointer
IntPtr m_ptr = CreateFileMapping(f_ptr, IntPtr.Zero, PAGE_READWRITE, 0, 0, "MyMapping");

// map view pointer
IntPtr view_ptr = MapViewOfFileEx(m_ptr, FILE_MAP_WRITE, 0, 0, 0, IntPtr.Zero);

// EDIT FILE CONTENTS

FlushViewOfFile(view_ptr, 0);
UnmapViewOfFile(view_ptr);

CloseHandle(m_ptr);
4

2 に答える 2

0

ファイルの書き込み可能なビューを持っている人なら誰でも、いつでも書き込むことができます。両方の編集者が確実に変更を書き出せるようにしたい場合は、変更が重なっている場所で独自の競合解決を実行する必要があります。

これは、解決するのが非常に単純な問題のようには思えません。おそらく、複数の編集を制御された方法でマージできるようにする単純なドキュメント バージョン管理システムが必要です。

于 2010-11-29T17:18:59.747 に答える
0

1 つのアイデアは、名前付きミューテックス (非 NULL の名前パラメーターでFlushViewOfFile()呼び出すことによって作成できる) を取得しながら、書き込み (および呼び出し) を実行できるというものです。CreateMutex()

例 (エラー処理は省略):

HANDLE hMutex, hMap;
PVOID pView;

// In reality, it might be good to dynamically generate the name based on
// the file being mapped (eg. its volume and file ID, something like this..)
hMutex = CreateMutex(NULL, FALSE, TEXT("Local\\LockForThisFile"));

hMap = CreateFileMapping( /* ... */ );
pView = MapViewOfFile( /* ... */ );

// Some time later, when you need to do the writes...
//
WaitForSingleObject(hMutex, INFINITE);
PerformWrites(pView);
FlushViewOfFile(pView, 0);
ReleaseMutex(hMutex);

これにアクセスする方法によっては、読み取り中にロックも取得する必要がある場合があります。もちろん、これは同時実行を制限します。

ところで、その他いろいろ。解説:

  • これは、呼び出し時に「ビューの開始から終了まで」よりも具体的である場合にも、パフォーマンスが向上する可能性がありますFlushViewOfFile。たとえばn、オフセットiにバイトを書き込む場合は、 FlushViewOfFile(pView + i, n);. OS がダーティなページをチェックし、最小限の書き込みしか実行できない可能性があります (MSDN は、これが発生することを示唆しているようです)。それは私の推測です。

  • EXCEPTION_IN_PAGE_ERRORファイルをマッピングするときに、I/O が失敗した場合にポインターの逆参照を行うと、例外が発生する可能性があります。これらは SEH でキャッチできます (この MSDN ページのように)。

于 2010-11-29T17:21:39.717 に答える