2010-11-29 244 views
0

我打算使用內存映射打開一個文件。CreateFileMapping程序之間的同步?

該文件已被另一個進程以相同的方式打開,即它有自己的內存映射視圖打開並不時編輯該文件。

我希望自己編輯同一文件,並儘可能有效地與其他進程共享訪問權限,而不會由於每個進程的衝突而造成對另一進程的更改。

我可以首先打開的文件直接:

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); 
+0

確切的模擬是兩個線程訪問相同的數組。如果他們訪問相同的元素,則需要鎖定。一個有名的互斥體,通常。 – 2010-11-29 18:24:53

回答

0

任何有文件可寫視圖的人都可以隨時寫入。如果您希望兩個編輯者都能夠可靠地寫出更改,則必須在更改重疊的位置執行自己的衝突解決方案。

這似乎不是一個非常簡單的問題要解決 - 也許您需要一個簡單的文檔版本控制系統,以允許以受控方式合併多個編輯。

0

一個想法是,您可以在獲取已命名的互斥鎖(可以通過調用CreateMutex()並使用非NULL的名稱參數創建)時執行寫操作(和調用FlushViewOfFile())。

例如(省略處理錯誤):

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電話。例如,如果您在偏移量i處編寫n字節,則可能要說FlushViewOfFile(pView + i, n);。操作系統可能會檢查哪些頁面很髒,只做最少量的寫入(MSDN似乎暗示會發生這種情況),但也許它會在較小的範圍內做得更好;這只是我的一個猜測。

  • 映射文件時,如果I/O失敗,可以執行指針取消引用的異常EXCEPTION_IN_PAGE_ERROR。你可以抓住那些與SEH(如在this MSDN page)。

相關問題