Безопасно ли иметь несколько процессов, записывающих в один и тот же файл одновременно? [CentOs 6, ext4] - PullRequest
44 голосов
/ 21 октября 2011

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

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

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

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

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

Ответы [ 2 ]

26 голосов
/ 25 октября 2011

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

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

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

24 голосов
/ 21 октября 2011

нет, как правило, это небезопасно!

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

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

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


EDIT

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

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

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

Цитата:

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

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

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


Вот соответствующий пост: (Отметьте галочкой ответ Байера! принятый ответ не верен / не актуален.)

Безопасно ли передавать несколько параллельных процессов в один файл, используя >>?


РЕДАКТИРОВАТЬ 2:

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...