Безопасно иметь несколько процессов пишут в один и тот же файл одновременно? [В CentOS 6, в ext4]
Я создаю систему, в которой несколько подчиненных процессов взаимодействуют через доменные сокеты unix, и они пишут в тот же файл в то же время. Я никогда не изучал файловые системы или эту конкретную файловую систему (ext4), но кажется, что здесь может быть какая-то опасность.
каждый процесс записывает в непересекающееся подмножество выходного файла (т. е. в записываемых блоках нет перекрытия). Например, P1
записывает только первые 50% файла и P2
записывает только до вторых 50%. Или, может быть,P1
пишет только нечетные блоки, в то время как P2
записывает четные блоки.
безопасно ли есть P1
и P2
(выполняется одновременно в отдельных потоках) запись в один и тот же файл без использования блокировки? Другими словами, неявно ли файловая система накладывает какую-то блокировку?
Примечание: к сожалению, я не могу выводить несколько файлов и присоединяться к ним позже.
Примечание: мое чтение с момента публикации этого вопроса не согласуется с единственным опубликованным ответом ниже. Все, что я читал, говорит о том, что я хочу делать хорошо, в то время как респондент ниже настаивает на том, что я делаю небезопасно, но я не могу различить описанную опасность.
2 ответов
то, что вы делаете, кажется совершенно нормальным, если вы используете POSIX "raw" IO syscalls, такие как read (), write (), lseek() и так далее.
Если вы используете c stdio (fread (), fwrite () и friends) или какую-либо другую библиотеку языковой среды выполнения, которая имеет свою собственную буферизацию пользовательского пространства, то ответ "Tilo" релевантен, в том, что из-за буферизации, которая в некоторой степени находится вне вашего контроля, различные процессы могут перезаписывать данные друг друга.
блокировка ОС Wrt, в то время как POSIX утверждает, что запись или чтение меньше размера PIPE_BUF являются атомарными для некоторых специальных файлов (труб и FIFO), нет такой гарантии для обычных файлов. На практике я думаю, что, скорее всего, IO внутри страницы являются атомарными, но такой гарантии нет. ОС выполняет внутреннюю блокировку только в той мере, в какой это необходимо для защиты собственных внутренних структур данных. Для сериализации доступа к файлам можно использовать блокировки файлов или какой-либо другой механизм межпроцессной связи. Но, все это относится только к вам, у вас есть несколько процессов, выполняющих ввод-вывод в одну и ту же область файла. В вашем случае, поскольку ваши процессы делают IO для разъединения разделов файла, ничто из этого не имеет значения, и вы должны быть в порядке.
нет, как правило, это небезопасно делать!
вам нужно получить монопольную блокировку записи для каждого процесса-это означает, что все остальные процессы будут ждать, пока один процесс пишет в файл.. чем больше интенсивных процессов ввода-вывода, тем дольше время ожидания.
лучше иметь один выходной файл для каждого процесса и форматировать эти файлы с меткой времени и идентификатором процесса в начале строки, чтобы вы могли позже объединить и отсортировать эти выходные файлы в автономном режиме.
совет: проверьте формат файла файлов журнала веб-сервера - они сделаны с отметкой времени в начале строки, поэтому они могут быть позже объединены и отсортированы.
редактировать
процессы UNIX используют определенный / фиксированный размер буфера при открытии файлов (например, 4096 байт) для передачи данных в файл на диске и из него. Как только буфер записи заполнен, процесс сбрасывает его на диск - это означает: он пишет полный полный буфер на диск! Обратите внимание, что это происходит, когда буфер полон! -- нет, когда есть конец линии! Это означает, что даже для одного процесса, который записывает в файл текстовые данные, ориентированные на строки, эти строки обычно вырезаются где-то посередине во время сброса буфера. Только в конце, когда файл закрывается после записи, можно предположить, что файл содержит полные строки!
Так в зависимости от когда ваш процесс решит потопить их буферы, они пишут в разное время в файл - например, порядок не является детерминированным / предсказуемым, когда буфер сбрасывается в файл, вы можете Не предполагайте, что он будет писать только полные строки -- например,обычно он будет писать частичные строки, тем самым испортив выход, если несколько процессов очищают свои буферы без синхронизации.
проверьте эту статью в Википедии: http://en.wikipedia.org/wiki/File_locking#File_locking_in_UNIX
цитата:
операционные системы Unix (включая Linux и Mac OS X от Apple, иногда называют Дарвином)обычно не автоматически блокировать открытые файлы или запуск программ. несколько видов файл-фиксируя механизмов доступно в различных вариантах Unix и во многих операционных системах поддержите больше чем один вид для совместимость. Два наиболее распространенных механизмы-fcntl (2) и flock(2). Третий такой механизм lockf (3), который может быть отдельным или может быть реализован с использованием первые два примитива.
вы должны использовать flock, или мьютексы синхронизировать процессы и убедитесь, что только один из них может писать в файл одновременно.
Как я уже упоминал ранее, вероятно, быстрее, проще и более прямолинейно иметь один выходной файл для каждого процесса, а затем при необходимости объединить эти файлы (в автономном режиме). этот подход используется некоторыми веб-серверами, например, которым необходимо войти в несколько файлов из нескольких потоков - и нужно убедиться, что все разные потоки являются высокопроизводительными (например, не нужно ждать друг друга на блокировке файла).
вот связанный пост: (отметьте ответ Байера! принятый ответ не является правильным/уместным.)
это безопасно передавать вывод нескольких параллельных процессов в один файл с помощью >>?
EDIT 2:
в комментарии Вы сказали, что хотите записать двоичные блоки данных фиксированного размера из разных процессов в один и тот же файл.
только в том случае, если размер вашего блока точно соответствует размеру файла-буфера системы, это может работать!
убедитесь, что ваша фиксированная длина блока является именно файловым буфером системы размер. В противном случае вы попадете в ту же ситуацию, что и с незавершенными строками. например, если вы используете 16K блоков, а система использует 4K блоков, то в целом вы увидите 4K блоков в файле в кажущемся случайном порядке - нет никакой гарантии, что вы всегда будете видеть 4 блока подряд из одного и того же процесса