Подтвердить что ты не робот

Безопасно ли одновременно записывать несколько процессов в один и тот же файл? [CentOs 6, ext4]

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

Каждый процесс записывает в непересекающееся подмножество выходного файла (т.е. в написанных блоках нет перекрытия). Например, P1 записывает только первые 50% файла, а P2 записывает только на второй 50%. Или, возможно, P1 записывает только блоки с нечетным номером, а P2 записывает четные блоки.

Безопасно ли иметь P1 и P2 (работает одновременно на отдельных потоках), записывая в тот же файл без какой-либо блокировки? Другими словами, файловая система накладывает какую-то блокировку неявно?

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

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

4b9b3361

Ответ 1

То, что вы делаете, выглядит отлично, если вы используете POSIX "raw" IO syscalls, такие как read(), write(), lseek() и т.д.

Если вы используете C stdio (fread(), fwrite() и друзей) или какую-то другую библиотеку времени исполнения, которая имеет собственную буферизацию в пользовательском пространстве, тогда ответ "Tilo" имеет значение, поскольку из-за буферизации, которая в какой-то степени вне вашего контроля, различные процессы могут перезаписывать друг друга.

Заблокировать OS OS, в то время как POSIX заявляет, что пишет или читает меньше, чем размер PIPE_BUF, является атомарным для некоторых специальных файлов (трубок и FIFO), для обычных файлов такой гарантии нет. На практике я думаю, что вероятность того, что IO на странице будет атомарной, но такой гарантии нет. ОС только блокирует внутренне в той мере, в какой это необходимо для защиты собственных внутренних структур данных. Для сериализации доступа к файлам можно использовать блокировки файлов или какой-либо другой механизм взаимодействия между процессами. Но все это относится только к тому, что у вас есть несколько процессов, выполняющих IO в один и тот же регион файла. В вашем случае, когда ваши процессы выполняют IO для разделяемых разделов файла, ничего из этого не имеет значения, и вы должны быть в порядке.

Ответ 2

нет, это небезопасно!

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

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

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


ИЗМЕНИТЬ

Процессы UNIX используют определенный/фиксированный размер буфера при открытии файлов (например, 4096 байт) для передачи данных в файл и из него. Как только буфер записи заполнен, процесс удаляет его на диск - это означает: он записывает полный полный буфер на диск! Обратите внимание, что это происходит, когда буфер заполнен! - нет, когда есть конец линии! Это означает, что даже для одного процесса, который записывает текстовые текстовые данные в файл, эти строки обычно вырезаются где-то посередине в момент сброса буфера. Только в конце, когда файл закрыт после записи, вы можете предположить, что файл содержит полные строки!

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

Проверьте эту статью в Википедии: http://en.wikipedia.org/wiki/File_locking#File_locking_in_UNIX

Цитата:

Операционные системы Unix (включая Linux и Apple Mac OS X, иногда называемый Дарвином) обычно не автоматически блокирует открытые файлы или запущенных программ. Несколько видов механизмов блокировки файлов: доступны в разных вариантах Unix и многих операционных системах поддержка более одного вида для совместимости. Два наиболее распространенных Механизмами являются fcntl (2) и стая (2). Третий такой механизм lockf (3), которые могут быть отдельными или могут быть реализованы с использованием любой из первые два примитива.

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

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


Вот связанная публикация: (Отметить, что Марк Байер отвечает! принятый ответ неверен/имеет значение.)

Безопасно ли вывести вывод нескольких параллельных процессов в один файл с помощью → > ?


ИЗМЕНИТЬ 2:

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

Только в том случае, если размер вашего блока равен размеру системного файла-буфера, может ли это работать!

Убедитесь, что фиксированная длина блока - это размер системного файла-буфера. В противном случае вы столкнетесь с той же ситуацией, что и с незавершенными линиями. например если вы используете блоки 16k, а система использует 4k-блоки, тогда в общем случае вы увидите 4k блоков в файле в порядке, по-видимому, случайном порядке - нет гарантии, что вы всегда увидите 4 блока подряд из того же процесса