Что происходит, когда вы читаете файл, когда он перезаписан?

26

Предположим, я прочитал (cat) файл, в то время как другой процесс переписывает его содержимое. Является ли выход предсказуемым? Что случилось бы?

Левен
источник
3
Поведение не определено, вы никогда не должны этого делать.
маргаритка

Ответы:

19

Это зависит от того, что делает писатель.

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

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

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

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

Жиль "ТАК - перестань быть злым"
источник
Жиль, ваше объяснение также применимо в ftp/ sftpсценарии? Скажем, процесс начинает читать переданный ftpфайл, в то время как другая версия того же файла перезаписывает его из-за новой передачи.
iruvar
@ 1_CR Да. В этом случае писатель и читатель являются процессами ftpd.
Жиль "ТАК - перестать быть злым"
в чем тут смысл обгонять?
Виктор Чой
@VictorChoy Стандартное значение: начинать позади / после кого-то другого и в какой-то момент двигаться впереди него.
Жиль "ТАК - перестань быть злым"
18

Это классическое состояние гонки, поэтому результат непредсказуем по определению.

Среди прочего, это зависит от

  • fopen(3)или open(2)режимы записи,
  • как / если писатель буферизирует свой вывод,
  • как читатель читает файл,
  • разница в скорости между читателем и писателем,
  • разница во времени между чтением и началом писателя.
  • И, конечно же, на современных многоядерных машинах все усложняется еще более низкими факторами (например, планированием процессов).

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

Алексиос
источник
1
Этот ответ гораздо более полный, чем мой. Удаляя мой ответ
убийца
0

Предыдущие респонденты имеют более подробные объяснения, чем это, но вот трюк, который определенно работает, в значительной степени делая именно то, что он хочет:

$ tail -f <filename>

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

Уиллоуби Уилл
источник