Будет ли «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.

  • inotifywait различные действия по файлу или директории
  • Создание списка файлов, удаление «дубликатов» с различным суффиксом
  • Как безопасно экспортировать устройство (HDD)?
  • Создание 50 каталогов с 50 файлами внутри
  • Как найти частоту появления строк, содержащихся в файле?
  • История доступа к файлу
  • Как отсортировать файл на основе раздела поля
  • Могут ли каталоги и файлы наследовать те же разрешения, что и родительский каталог?
  • Помогла ли моя команда $ mv '* .mobi' соединить мои файлы?
  • Разделить и отредактировать полученный файл в том же конвейере
  • Что означает изменение файла / каталога?
  • Interesting Posts

    Как узнать, какой метод использовался для входа (пароль против ключевого файла) из bashrc

    Как сопоставить 2 больших файла и распечатать разницу в сценарии оболочки

    Как узнать, сколько контейнера памяти lxc разрешено потреблять?

    Скопируйте шаблон соответствия линии рядом с другой соответствующей строкой шаблона, используя sed

    Почему в Cinnamon / Linux / Xorg отключен ключ Scroll Lock?

    Могу ли я ускорить вставку в vim?

    Изменить почтовый ящик mailx

    Как использовать wifi с помощью hotspot без прокси-сервера?

    debian неустойчивый сбой

    Как я могу отключить сеансы SSH?

    Подождите, пока появится окно X (исчезнет)

    Каков минимальный круглый интервал шифрования, поддерживаемый Linux?

    2 монитора на графическом процессоре, 1 монитор интегрированной графики

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

    В чем разница между «tail -f» и «tail -F»?

    Linux и Unix - лучшая ОС в мире.