Вопрос

В общем, что мы можем считать само собой разумеющимся, когда мы добавляем к файлу в UNIX из нескольких процессов?Возможно ли потерять данные (один процесс перезаписывает изменения другого)?Возможно ли, чтобы данные были искажены?(Например, каждый процесс добавляет по одной строке за каждое добавление в файл журнала, возможно ли, что две строки будут искажены?) Если добавление не является атомарным в вышеуказанном смысле, то каков наилучший способ обеспечить взаимное исключение?

Это было полезно?

Решение

Запись, размер которой меньше 'PIPE_BUF', должна быть атомарной.Это должно быть не менее 512 байт, хотя оно легко может быть больше (в Linux, похоже, оно установлено на 4096).

Это предполагает, что вы говорите обо всех полностью совместимых с POSIX компонентах.Например, это неверно в NFS.

Но предполагая, что вы записываете в файл журнала, который открыли в режиме 'O_APPEND', и сохраняете длину строк (включая новую строку) в байтах 'PIPE_BUF', вы должны иметь возможность нескольких записей в файл журнала без каких-либо проблем с повреждением.Любые прерывания будут поступать до или после записи, а не в середине.Если вы хотите, чтобы целостность файла сохранилась после перезагрузки, вам также необходимо вызвать fsync(2) после каждой записи, но это ужасно сказывается на производительности.

Разъяснение:прочтите комментарии и Ответ Оза Соломона.Я не уверен, что O_APPEND предполагается, что это PIPE_BUF атомарность размера.Вполне возможно, что это просто то, как реализован Linux write(), или это может быть связано с размерами блоков базовой файловой системы.

Другие советы

Редактировать: Обновлено в августе 2017 года с последними результатами Windows.

Я собираюсь дать вам ответ со ссылками на тестовый код и результаты, как автор предложенного Повышение.AFIO который реализует асинхронную файловую систему и библиотеку файлового ввода-вывода C ++.

Во-первых, O_APPEND или эквивалентный FILE_APPEND_DATA в Windows означает, что приращения максимального размера файла ("длина" файла) составляют атомный в разделе "параллельные авторы".Это гарантируется POSIX, и все Linux, FreeBSD, OS X и Windows реализуют это правильно.Samba также реализует это правильно, NFS до версии 5 - нет, поскольку ей не хватает возможности wire format для атомарного добавления.Поэтому, если вы откроете свой файл с помощью append-only, одновременные записи не будут прерываться по отношению друг к другу ни в одной основной операционной системе если только не задействована NFS.

Однако одновременный читает к атомарным добавлениям мочь смотрите раздел "разорванные записи" в зависимости от операционной системы, файловой системы и того, с какими флагами вы открыли файл - приращение максимального размера файла является атомарным, но видимость записей по отношению к чтениям может быть, а может и не быть атомарной.Вот краткое описание флагов, операционной системы и файловой системы:


Нет O_DIRECT/FILE_FLAG_NO_BUFFERING O_DIRECT/FILE_FLAG_NO_BUFFERING:

Microsoft Windows 10 с NTFS:атомарность обновления = 1 байт до 10.0.10240 включительно, начиная с 10.0.14393 не менее 1 МБ, вероятно, бесконечно (*).

Linux 4.2.6 с ext4:атомарность обновления = 1 байт

FreeBSD 10.2 с ZFS:атомарность обновления = не менее 1 Мб, вероятно, бесконечно (*)

O_DIRECT/ФАЙЛ_ФЛАГА_НО_БУФЕРИЗАЦИИ:

Microsoft Windows 10 с NTFS:атомарность обновления = до 10.0.10240 включительно до 4096 байт, только если страница выровнена, в противном случае 512 байт, если FILE_FLAG_WRITE_THROUGH отключен, еще 64 байта.Обратите внимание, что эта атомарность, вероятно, является особенностью PCIe DMA, а не разработана в.Начиная с 10.0.14393, по крайней мере, 1 Мб, вероятно, бесконечно (*).

Linux 4.2.6 с ext4:атомарность обновления = не менее 1 Мб, вероятно, бесконечно (*).Обратите внимание, что более ранние версии Linux с ext4 определенно не превышали 4096 байт, XFS, безусловно, имела пользовательскую блокировку, но, похоже, что недавний Linux, наконец, исправил это.

FreeBSD 10.2 с ZFS:атомарность обновления = не менее 1 Мб, вероятно, бесконечно (*)


Вы можете ознакомиться с необработанными результатами эмпирического тестирования по адресу https://github.com/ned14/afio/tree/master/programs/fs-probe.Обратите внимание, что мы проверяем на разрыв смещений только на 512-байтовых кратных, поэтому я не могу сказать, приведет ли частичное обновление 512-байтового сектора к разрыву во время цикла чтения-изменения-записи.

Итак, чтобы ответить на вопрос OP, записи O_APPEND не будут мешать друг другу, но чтение, параллельное записи O_APPEND, вероятно, приведет к разрыву записей в Linux с ext4, если O_DIRECT не включен, после чего ваши записи O_APPEND должны быть кратны размеру сектора.


(*) "Вероятно, бесконечный" вытекает из этих предложений в спецификации POSIX:

Все следующие функции должны быть атомарными по отношению друг к другу в эффектах, указанных в POSIX.1-2008, когда они работают с обычными файлами или символическими ссылками ...[множество функций] ...читать() ...write() ...Если каждый из двух потоков вызывает одну из этих функций, каждый вызов должен либо видеть все указанные эффекты другого вызова, либо ни один из них. [Источник]

и

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

но наоборот:

Этот том POSIX.1-2008 не определяет поведение параллельного выполняет запись в файл из нескольких процессов.Приложения должны использовать некоторую форму управления параллелизмом. [Источник]

Вы можете подробнее прочитать об их значении в этом ответе

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

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

В Linux + ext3 его размер равен 4096, а в Windows + NTFS - 1024.Смотрите комментарии ниже для получения дополнительных размеров.

Вот что говорится в стандарте: http://www.opengroup.org/onlinepubs/009695399/functions/pwrite.html.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top