CreateFileMapping синхронно между программами? - PullRequest
0 голосов
/ 29 ноября 2010

Я планирую открыть файл, используя отображение памяти.

Файл уже открыт другим процессом таким же образом, т. Е. У него открыто собственное представление карты памяти и время от времени редактируется файл.

Я хочу отредактировать тот же файл сам и поделиться доступом к нему с другим процессом настолько эффективно, насколько это возможно, без надежды на конфликт между каждым процессом, перезаписывая изменения, сделанные другим.

Прежде всего, я могу открыть файл напрямую:

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

Ответы [ 2 ]

0 голосов
/ 29 ноября 2010

Одна идея состоит в том, что вы могли бы делать записи (и вызов FlushViewOfFile()) при получении именованного мьютекса (который вы можете создать, вызвав CreateMutex() с параметром имени, отличным от NULL)..

Например (обработка ошибок опущена):

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);.Вполне возможно, что ОС может проверить, какие страницы являются грязными, и выполнять только минимальное количество операций записи (MSDN, похоже, предполагает, что это происходит), но, возможно, это будет лучше с меньшим диапазоном;это всего лишь предположение с моей стороны.

  • При отображении файлов вы можете получить EXCEPTION_IN_PAGE_ERROR исключений, выполняющих разыменование указателя в случае сбоя ввода-вывода.Вы можете поймать их с помощью SEH (как в на этой странице MSDN ).

0 голосов
/ 29 ноября 2010

Любой человек с возможностью записи в файл может написать в него в любое время.Если вы хотите, чтобы оба редактора могли надежно записывать изменения, вам придется выполнить собственное разрешение конфликтов, когда изменения перекрываются.

Это не кажется очень простой проблемой для решения - возможно, вам нужна простая система контроля версий документов, позволяющая объединять несколько изменений контролируемым образом.

...