Копирование файлов при записи в Windows - PullRequest
1 голос
/ 06 марта 2019

У меня есть 3 процесса, взаимодействующих по именованным каналам: сервер, писатель, читатель.Основная идея заключается в том, что Writer может хранить огромные (~ ГБ) двоичные двоичные объекты на сервере , и считыватели могут его извлечь.Но вместо отправки данных по именованному каналу используется отображение памяти.

Сервер создает неназванное отображение с файловой поддержкой с CreateFileMapping с защитой PAGE_READWRITE, затем дублирует дескрипторв писатель .После того, как писатель выполнил свою работу, дескриптор дублируется на любое количество читателей .

писатель отображает дескриптор с помощью MapViewOfFile в режиме FILE_MAP_WRITE.

Считыватель отображает маркер с MapViewOfFile в режиме FILE_MAP_READ|FILE_MAP_COPY.

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

Проблема
Когда считыватель пытается записать в отображение, он умирает с ошибкой сегментации, как если бы FILE_MAP_COPY не рассматривалось.Что не так с вышеописанным методом?В соответствии с MSDN это должно работать ...

У нас такой же механизм реализован и в linux (с mmap и передачей fd во вспомогательных буферах AF_UNIX), и он работает как положено.

Ответы [ 2 ]

5 голосов
/ 06 марта 2019

проблема здесь в том, что MapViewOfFile плохо спроектированы или / и задокументированы. это оболочка (с ограниченной функциональностью) свыше ZwMapViewOfSection. параметр dwDesiredAccess MapViewOfFile преобразован в Win32Protect параметр ZwMapViewOfSection.

комбинация FILE_MAP_READ|FILE_MAP_COPY преобразована в PAGE_READONLY защиту страницы, потому что это вы и получите ошибку страницы при записи.

вам нужно использовать только флаг FILE_MAP_COPY - он конвертируется в PAGE_WRITECOPY защиту страницы и в этом случае все будет работать.

лучшее решение конечно прямого использования ZwMapViewOfSection с PAGE_WRITECOPY защита страницы

1 голос
/ 06 марта 2019

TL: DR: RbMm правильно, вы должны передать просто FILE_MAP_COPY в MapViewOfFile, чтобы получить режим копирования при записи.

Текущая документация Microsoft неверна, в ней неправильно указано, что FILE_MAP_COPY может быть ИЛИ с FILE_MAP_<ALL_ACCESS|READ|WRITE>.

Глядя на более старые версии MSDN , он правильно говорит , что вы должны выбрать один из режимов доступа:

Тип доступа к представлению файла и, следовательно, защита страниц, отображаемых файлом. Этот параметр может быть одним из следующих значений .

  • FILE_MAP_WRITE
  • FILE_MAP_READ
  • FILE_MAP_ALL_ACCESS
  • FILE_MAP_COPY

Больше не актуально, но все же удивительно, в Windows 95/98 / ME поведение копирования при записи применяется только к файлу, записи распространяются на представления в других процессах!

...