我计划使用内存映射打开文件。
该文件已被其他进程以相同的方式打开,即它打开了自己的内存映射视图,并不时编辑该文件。
我希望自己编辑同一个文件,并尽可能有效地与其他进程共享访问权限,而不会因为每个进程覆盖另一个进程所做的更改而发生冲突。
我首先可以直接打开文件:
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 :(得分:0)
任何具有该文件可写视图的人都可以随时写入该文件。如果您希望两个编辑器能够可靠地写出更改,则必须在更改重叠的情况下执行自己的冲突解决方案。
这似乎不是一个非常简单的问题需要解决 - 也许您需要一个简单的文档版本控制系统,以允许以受控方式合并多个编辑。
答案 1 :(得分:0)
一个想法是,您可以在获取命名互斥锁时执行写入(以及FlushViewOfFile()
调用)(您可以通过使用非NULL的名称参数调用CreateMutex()
来创建)。 / p>
例如(省略错误处理):
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);
根据您访问此方式的方式,您可能还需要在阅读时获取锁定。这当然会限制你的并发性。
顺便说一下,其他一些misc。评论:
如果您在FlushViewOfFile
来电时比“从视图开始到结束”更具体,这也可能表现得更好。例如,如果您在偏移n
处写入i
个字节,则可能需要说FlushViewOfFile(pView + i, n);
。操作系统有可能检查哪些页面是脏的并且只进行最少量的写入(MSDN似乎暗示会发生这种情况),但也许它会在较小的范围内做得更好;这只是我的一个猜测。
映射文件时,如果I / O失败,您可以获取指针解除引用的EXCEPTION_IN_PAGE_ERROR
个异常。您可以捕获那些有SEH的人(如this MSDN page)。