Будет ли «unlink» или «переименовать» переносимо и атомарно сделать «ссылку» неудачной?

Вопрос

Предположим, что у меня есть некоторая директория (файл, named pipe / socket, whatever) в pathname /tmp/foo и какая-то другая не-директория на пути /tmp/bar . Затем два (или более) процесса начинают выполнять одновременно:

Один из способов:

 unlink('/tmp/foo') /* or rename('/tmp/foo', '/tmp/removed') */ unlink('/tmp/bar') /* or rename('/tmp/bar', '/tmp/removed') */ 

Процесс два (и т. Д.) Делает:

 link('/tmp/foo', '/tmp/bar') 

Насколько я понимаю, нет способа, которым могли бы быть успешны два процесса (либо попытка link(2) в то время как /tmp/foo все еще присутствует, и в этом случае /tmp/bar также присутствует, поэтому он должен терпеть неудачу с EEXIST или /tmp/foo ушел, поэтому он должен завершиться неудачно с ENOENT ).

Но эта интуиция основывается на предположении, что системные вызовы unlink(2) и / или rename(2) неотъемлемо последовательны в их невоспроизводимых эффектах, поэтому я ищу подтверждение моего понимания: существует ли какая-либо система nix-типа чье ядро ​​позволяет двум unlink(2) и / или rename(2) чтобы добиться успеха, но одновременно приводит к тому, что link(2) также преуспевает (из-за переупорядочения отмены /tmp/foo и /tmp/bar а не абстрагировать / скрывать это от процесса, вызывающего link(2) , или через какое-то другое причудливое состояние гонки / ошибка)?

Текущее понимание

Я прочитал manpages для unlink(2) , rename(2) и link(2) для Linux и несколько BSD и спецификацию POSIX для этих функций. Но я не думаю, что они действительно содержат что-то успокаивающее в этом вопросе, при тщательном рассмотрении. По крайней мере, с rename(2) нам обещано, что место назначения заменено атомарно, если оно уже присутствует ( ошибки в самой ОС в стороне ), но ничего больше.

Я видел утверждения о том, что несколько одновременных исполнений rename(foo, qux) будут атомарно и портативно иметь все, кроме одного переименования, с ENOENT – так что это многообещающе! Я просто не уверен, что это может быть расширено до того, что link(foo, bar) терпит неудачу с ENOENT при тех же обстоятельствах.

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

Я понимаю, что это одна из тех, которые «не могут доказать отрицательные» ситуации – мы можем в лучшем случае заметить, что нет никаких доказательств того, что существует такая же система, как и nix-подобная система, которая позволит достичь успеха в двух технологиях link(2) .

Таким образом, я ищу ответы, охватывающие как можно больше * nix-подобных систем (по крайней мере, Linux, OS X и различные BSD, но в идеале также запатентованные системы для использования в некоторых системах, такие как Solaris 10) от людей, которые имеют достаточное знакомство с этими системами и этот узкий набор проблем (атомные / хорошо упорядоченные операции файловой системы), что они уверены (насколько это реально реально), что они будут знать о таких проблемах, как вышеупомянутый Mac OS X rename(2) -не-фактически-атомную ошибку, если они существуют на платформах, с которыми они знакомы. Это дало бы мне достаточную уверенность в том, что это работает так, как я думаю, это достаточно переносимо, чтобы полагаться.

Итоговая записка

Это не проблема «проблема X / Y» – нет основной проблемы, на которую можно ответить, обратившись ко мне к различным механизмам блокировки / IPC или чему-то еще, что работает вокруг неопределенности в отношении того, как взаимодействуют эти конкретные системные вызовы: я специально хочу чтобы знать, можно ли полагаться на вышеупомянутые системные вызовы, портативно взаимодействующие, как ожидалось, в * nix-подобных системах в практическом использовании сегодня.

One Solution collect form web for “Будет ли «unlink» или «переименовать» переносимо и атомарно сделать «ссылку» неудачной?”

Посмотрите на такие стандарты, как POSIX, на гарантии мобильности. На практике большинство POSIX-совместимых систем имеют небольшие отклонения от спецификаций, но, как правило, вы можете положиться на гарантии, указанные в спецификации. Большинство современных устройств соответствуют спецификации, даже если они официально не прошли проверку. Возможно, их нужно запустить в режиме POSIX, например, установить POSIXLY_CORRECT=1 с помощью bash или убедиться, что /usr/xpg4/bin впереди /bin и /usr/bin в PATH на Solaris.

Single Unix v2 (более раннее расширение POSIX) имеет в виду link :

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

О rename :

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

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

Кроме того, порядок операций гарантирован: в C ; гарантирует последовательное выполнение; в sh,; / newline гарантирует последовательное выполнение (как и && и т. д.); другие языки программирования предлагают аналогичные гарантии. Итак, в

 unlink("/tmp/foo"); unlink("/tmp/bar"); 

гарантируется, что нет времени, когда /tmp/foo существует, но не /tmp/bar (предполагается, что /tmp/bar существует изначально). Следовательно, выполнение параллельного процесса, выполняющего link("/tmp/foo", "/tmp/bar") не может быть выполнено.

Обратите внимание, что атомарность не гарантирует упругость . Атомарность – это наблюдаемое поведение в живой системе. Устойчивость в контексте файловых систем связана с тем, что происходит в случае сбоя системы. Многие файловые системы жертвуют стойкостью к производительности, поэтому, если выполнение unlink("foo"); unlink("bar"); unlink("foo"); unlink("bar"); (с текущим каталогом на диске на диске), возможно, что bar будет удалена, а foo останется позади.

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

  • длительная задержка в (win) rar перед добавлением файлов
  • Как я могу просмотреть вывод файла программы в текстовый файл по мере его заполнения?
  • Как файлы с защитой от ненадежного приложения защищены в Linux
  • Требование пароля для всех файлов с указанным расширением
  • Копирование только новых файлов
  • Транспонирование трехмерного тензора, воспроизводимого файлами
  • Сделать доступным только для чтения каталог для других пользователей
  • Список файлов + каталог, рекурсивно отсортированный по времени доступа
  • Перемещение файлов, не подлежащих записи, и перемещение непереписываемых каталогов
  • Как изменить «изменение даты» нескольких папок, чтобы они были такими же .mkv, что внутри каждого, используя Cygwin
  • Как навсегда изменить разрешение файла / каталога
  • Interesting Posts
    Linux и Unix - лучшая ОС в мире.