Является ли rename() атомарным?
Я не могу проверить это с помощью экспериментов и не могу собрать это из страниц руководства.
Скажем, у меня есть два процесса, один перемещает (переименовывает) файл1 из каталога1 в каталог2. Скажем, другой процесс, выполняющийся одновременно, копирует содержимое directory1 и directory2 в другое место. Возможно ли, что копия произойдет таким образом, что и directory1, и directory2 покажут file1 - то есть directory1 копируется перед перемещением, а directory2 - после перемещения первым процессом.
По сути, rename() является атомным системным вызовом?
Спасибо
3 ответа
И да и нет.
Функция rename() атомарна, если ОС не падает. Он не может быть разделен какой-либо другой файловой системой.
В случае сбоя системы вы можете увидеть операцию ln().
Также обратите внимание, что при работе в сетевой файловой системе вы можете получить ENOENT, если операция прошла успешно. Локальная файловая система не может сделать это для вас.
Это очень поздний ответ, но... да rename()
атомно, но не в смысле вашего вопроса. Под Linux rename(2)
говорит:
Однако при перезаписи, вероятно, будет окно, в котором oldpath и newpath ссылаются на переименованный файл.
Но rename()
все еще атомарен в очень важном смысле: если вы используете его для перезаписи файла, вы получите либо старую, либо новую версию и ничего больше.
[обновление: но, как указывает @jonas-wielicki в комментариях, вам необходимо убедиться, что файл, который вы переименовываете, действительно содержит актуальное содержимое, используя fsync()
и друзья.]
Если newpath уже существует, он будет атомарно заменен (при соблюдении нескольких условий; см. ОШИБКИ ниже), чтобы не было точки, в которой другой процесс, пытающийся получить доступ к newpath, обнаружит, что он отсутствует.
Если вы увидите ОШИБКИ, вы обнаружите, что переименование может произойти сбой, но это никогда не нарушит атомарность.
Это все из справочной страницы Linux. Что я не знаю, если вы делаете rename()
в сетевой файловой системе, где на сервере работает другая ОС. Есть ли у клиента надежда на гарантию атомности? Я сомневаюсь.
Я не уверен, что "в основном" часть вашего вопроса верна. Если у вас нет какой-либо синхронизации между ними, не имеет значения, как выглядит атомарное переименование. Если копия каталога попадет туда до переименования, вы будете иметь file1 в обоих местах.
Я не уверен, имели ли вы в виду потоки или процессы, но если есть механизмы блокировки для обоих, блокировки потоков являются самыми простыми, потому что они не должны пересекать границы процесса.
Руководство GNU Libc говорит
Одна полезная особенность переименования состоит в том, что значение нового имени "атомарно" изменяется от любого ранее существующего файла с таким именем на его новое значение (то есть файл, который назывался старым именем). Нет момента, когда новое имя не существует "между" старым значением и новым значением. Если во время операции происходит сбой системы, оба имени могут существовать; но newname всегда будет целым, если оно вообще существует.