Как работает этот пример канонической стаи?

Когда необходимо синхронизировать программы (сценарии оболочки) через файловую систему, я нашел решение на основе flock, которое рекомендуется (должно также работают в NFS). Канонический пример использования внутри сценария (из http://linux.die.net/man/1/flock):

(
flock -s 200

# ... commands executed under lock ...

) 200>/var/lock/mylockfile 

Я не совсем понимаю, почему вся эта конструкция обеспечивает атомарность. В частности, мне интересно, в каком порядке выполняются flock -s 200 и 200>/var/lock/mylockfile, например, когда bash выполняет эти строки кода. Этот порядок гарантирован / детерминирован? Насколько я понимаю, это должно быть детерминированным, если эта идиома должна работать. Но поскольку подчиненная оболочка порождается в дочернем процессе, я не понимаю, как эти два процесса синхронизируются. Я уже вижу только состояние гонки между этими двумя командами.

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

В то же время, если кто-то знает, мне было бы интересно узнать, насколько безопасно выбрать какой-нибудь произвольный файловый дескриптор (например, 200 в примере), особенно в контексте большой файловой системы NFS с большим количеством клиентов.


person Dr. Jan-Philip Gehrcke    schedule 01.08.2013    source источник


Ответы (1)


Весь контекст ввода-вывода суб-оболочки (...) 200>/var/lock/mylockfile должен быть оценен - ​​и перенаправление ввода / вывода выполнено - до того, как какие-либо команды могут быть выполнены в суб-оболочке, поэтому перенаправление всегда предшествует flock -s 200. Подумайте, был ли стандартный вывод суб-оболочки передан другой команде; этот канал должен быть создан до создания подоболочки. То же самое относится к перенаправлению файлового дескриптора 200.

Выбор номера файлового дескриптора не имеет ни малейшего значения - кроме того, желательно не использовать файловые дескрипторы 0-2 (стандартный ввод, вывод, ошибка). Имя файла имеет значение; разные процессы могут использовать разные файловые дескрипторы; пока имя согласовано, все будет в порядке.

person Jonathan Leffler    schedule 01.08.2013
comment
Хорошо, спасибо, это имеет смысл при применении перспективы command -> pipe -> output_device. И просто для пояснения: также не имеет значения, если несколько экземпляров попытаются создать /var/lock/mylockfile одновременно, только один экземпляр, вызывающий flock -s 200, может выиграть, верно? - person Dr. Jan-Philip Gehrcke; 01.08.2013
comment
Итак, flock -s запрашивает разделяемую блокировку; это предотвращает изменение файла кем-либо, но позволяет нескольким процессам также блокировать его в общем режиме. Вы хотите, чтобы flock -x (или без флага) получила эксклюзивную блокировку. - person Jonathan Leffler; 01.08.2013
comment
Хорошо, теперь я понимаю stackoverflow.com/a/169969/145400. Еще раз спасибо! - person Dr. Jan-Philip Gehrcke; 01.08.2013
comment
С -w 10 в этом ответе код должен быть if flock -x -w 10 200; then ...use the file...; fi, тогда как код в настоящее время работает, предполагая, что тайм-аут не был превышен и блокировка была успешной. Комментарий также добавлен к другому посту. - person Jonathan Leffler; 01.08.2013
comment
Конечно. Не буду использовать с таймаутом. Еще одна вещь (может быть очевидной, но стоит спросить): блокировка автоматически снимается, как только подоболочка завершает работу, да? И rm /var/lock/mylockfile после всего блока кода сделает очистку, верно? - person Dr. Jan-Philip Gehrcke; 01.08.2013
comment
Да (блокировка автоматически снимается, когда суб-оболочка завершает работу). Да (удаление файла блокировки после того, как блок кода выполнит очистку). - person Jonathan Leffler; 01.08.2013