Запись размером меньше «PIPE_BUF» должна быть атомарной. Это должно быть не менее 512 байт, хотя легко может быть больше (похоже, в Linux установлено значение 4096).
Это предполагает, что вы говорите обо всех полностью совместимых с POSIX компонентах. Например, это не так в NFS.
Но при условии, что вы пишете в файл журнала, который вы открыли в режиме «O_APPEND», и сохраняете свои строки (включая новую строку) под байтами «PIPE_BUF», у вас должно быть несколько авторов записи в файл журнала без каких-либо проблем с повреждением. Любые прерывания поступят до или после записи, а не посередине. Если вы хотите, чтобы целостность файла сохранялась после перезагрузки, вам также нужно будет вызывать fsync(2)
после каждой записи, но это ужасно для производительности.
Уточнение : прочтите комментарии и ответ Оз Соломона . Я не уверен, что O_APPEND
он должен иметь PIPE_BUF
атомарность такого размера. Вполне возможно, что так реализовано в Linux write()
, или это может быть связано с размерами блоков базовой файловой системы.
fsync(2)
дает такую же гарантию, как иsync(2)
дает, и не оказывает такого большого влияния на производительность.PIPE_BUF
на этой странице применимо только к каналам и FIFO, а не к обычным файлам.Изменить: обновлено в августе 2017 года с последними результатами Windows.
Я дам вам ответ со ссылками на тестовый код и результаты как автор предложенного Boost.AFIO, который реализует асинхронную файловую систему и библиотеку ввода-вывода файлов C ++.
Во-первых, O_APPEND или эквивалентный FILE_APPEND_DATA в Windows означает, что приращения максимального размера файла («длина» файла) являются атомарными при одновременной записи. Это гарантируется POSIX, и Linux, FreeBSD, OS X и Windows все реализуют это правильно. Samba также реализует это правильно, NFS до v5 - нет, поскольку в нем отсутствует возможность форматирования проводов для атомарного добавления. Таким образом, если вы откроете файл только с добавлением, одновременные записи не будут разрываться относительно друг друга в любой основной ОС, если не задействована NFS.
Однако при одновременном чтении в атомарные добавления могут наблюдаться разорванные записи в зависимости от ОС, файловой системы и того, с какими флагами вы открывали файл - приращение максимального размера файла является атомарным, но видимость записи относительно чтения может или не может быть атомарным. Вот краткое описание флагов, ОС и файловой системы:
Нет 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 / FILE_FLAG_NO_BUFFERING:
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:
и
но наоборот:
Вы можете узнать больше об их значении в этом ответе
источник
Я написал сценарий для эмпирической проверки максимального размера атомарного присоединения. Сценарий, написанный на bash, порождает несколько рабочих процессов, которые все записывают сигнатуры рабочих в один и тот же файл. Затем он читает файл в поисках перекрывающихся или поврежденных подписей. Вы можете увидеть источник сценария в этом сообщении в блоге .
Фактический максимальный размер атомарного добавления зависит не только от ОС, но и от файловой системы.
В Linux + ext3 размер составляет 4096, а в Windows + NTFS - 1024. Дополнительные размеры см. В комментариях ниже.
источник
echo $line >> $OUTPUT_FILE
результатом будет один вызовwrite
независимо от размера$line
.Вот что говорится в стандарте: http://www.opengroup.org/onlinepubs/009695399/functions/pwrite.html .
источник