У нас есть файл, содержащий данные, которые всегда должны быть согласованными. Когда его нужно изменить, Process 1
создает новый файл, записывает новый файл с изменениями и использует mv
для переименования нового файла в старое имя файла.
Если у нас есть другой процесс, Process 2
которому необходимо прочитать этот файл, как мы можем гарантировать, что он всегда будет читать согласованный файл, т. е. mv
ошибка Process 1
во время чтения не приведет к повреждению данных?
решение1
Вы гарантируете это, создавая новый файл в той же файловой системе, что и старый файл, и используя rename(2)
функцию [1], которая гарантированно является атомарной.
В файловых системах Unix a rename(2)
действует только на записи каталога, он не повлияет на любой процесс, имеющий открытый дескриптор inode, на который указывает исходная запись dir; этот процесс продолжит чтение или запись в старый файл.
Обычно mv(1)
утилита просто вызывает rename(2)
, но в случае сбоя она может прибегнуть к удалению + копированию или другим сомнительным неатомарным операциям rename(2)
.
Обратите внимание, что нахождение двух файлов в одной файловой системе не гарантирует, что операция переименования rename(2)
будет успешной — существуют файловые системы, 9pfs
которые не поддерживают операцию переименования, поэтому ее приходится выполнять тем или иным способом.
[1] или даже лучше, renameat(2)
который предотвращает скрытое изменение ведущих путей к файлам из другого процесса, т.е. «атаки с использованием символических ссылок».