Является ли добавление в файл атомарным с Windows / NTFS? - PullRequest
3 голосов
/ 13 июня 2010

Если я пишу простой текстовый файл журнала из нескольких процессов, могут ли они перезаписать / повредить записи друг друга?

(По сути, этот вопрос Является ли добавление файла атомарным в UNIX? но для Windows / NTFS.)

Ответы [ 4 ]

12 голосов
/ 02 января 2012

Вы можете получить атомарный доступ к локальным файлам.Откройте файл с доступом FILE_APPEND_DATA (задокументировано в WDK ).Если вы пропустите доступ FILE_WRITE_DATA, то все записи будут игнорировать текущий указатель файла и будут выполняться в конце файла.Или вы можете использовать доступ FILE_WRITE_DATA и для записей добавления указать его в перекрывающейся структуре (Offset = FILE_WRITE_TO_END_OF_FILE и OffsetHigh = -1, задокументировано в WDK ).

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

2 голосов
/ 13 июня 2010

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

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

1 голос
/ 13 июня 2010

С этой страницы MSDN о создании и открытии файлов:

Приложение также использует CreateFile , чтобы указать, хочет ли оно предоставить общий доступ к файлу для чтения, записи, как для того, так и другого. Это известно как режим обмена. Открытый файл, который не является общим ( dwShareMode установлен на ноль), не может быть открыт снова ни приложением, которое открыло его, ни другим приложением, пока его дескриптор не будет закрыт. Это также называется эксклюзивным доступом.

и

Если указать режим доступа или совместного использования, который конфликтует с режимами, указанными в предыдущем вызове, CreateFile завершится ошибкой.

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

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

0 голосов
/ 13 июня 2010

Нет, это не так.Если вам это нужно, в Windows Vista / 7 есть Транзакционная NTFS .

...