flock vs lockf в Linux

19

Если lockf используется с смещением 0, каковы различия между flock и lockf при использовании в эксклюзивном режиме, если таковые имеются?

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

    
задан Dan McGrath 14.03.2014 в 16:48
источник

2 ответа

26

Практическая разница между flock() и lockf() заключается в семантике (поведение по отношению к закрытию и прохождению), применимости к NFS и другим общим файловым системам, а также то, являются ли консультативные блокировки видимыми для других процессов, используя fcntl() блокировки или нет.

Библиотека, которую вы используете, просто имеет логику для выбора желаемой семантики на основе текущей платформы.

Если семантика (поведение над передачей дескриптора, форкировка и т. д.) приемлема, вы должны предпочесть, что lockf() / fcntl() блокирует блокировку flock() в Linux, просто потому, что первая работает с файловыми системами NFS и т. д. в то время как последний нет. (В BSD и Mac OS X, я считаю, вам нужно явно использовать fcntl() .)

В Linux lockf() является просто оболочкой fcntl() , а flock() блокировки являются отдельными (и будут работать только на локальных файловых системах, а не на монтах NFS на ядрах до 2.6.12). То есть, у одного процесса может быть привилегированная исключительная блокировка flock() для файла, в то время как другой процесс имеет специальную блокировку fcntl() в том же файле. Оба являются консультативными блокировками, но они не взаимодействуют.

В Mac OS X и FreeBSD , lockf() / flock() / fcntl() блокирует все взаимодействия, хотя разработчикам рекомендуется использовать только один из интерфейсов в приложении. Однако только fcntl() блокирует работу монтирования NFS (и, очевидно, только если оба клиента и сервер NFS настроены на поддержку блокировок записей, что на удивление редко встречается в среде веб-хостинга, что является огромной причиной головных болей для некоторых веб-разработчиков (фреймворков).

В POSIX явно не указано, как должны взаимодействовать блокировки lockf() / flock() / fcntl() , и в прошлом были различия. Теперь ситуация немного успокоилась, и можно приблизительно сказать, что

  1. fcntl() блокировки являются наиболее надежными

    Во всех архитектурах они имеют наилучшие шансы работать прямо, например. общие файловые системы - например, монтируются NFS и CIFS.

  2. Чаще всего lockf() реализуется как «стенография» для fcntl()

    Другая альтернатива, как «стенография» для flock() , возможна, но в настоящее время редкая.

  3. fcntl() и flock() имеют разную семантику wrt. наследование и автоматические релизы

    fcntl() блокировок сохраняются в exec() , но не наследуются через fork() . Блокировки освобождаются, когда процесс владения закрывает любой дескриптор , ссылающийся на тот же файл.

    В Linux, FreeBSD и MAc OS X блокировки flock() связаны с открытым файловым дескриптором: передача дескриптора также передает блокировку. (В man-страницах указано, что «блокировка находится в файле, а не в дескрипторе файла» . Это не противоречие. Это просто означает, что lock применяет к файл по-прежнему связан с дескриптором, таким образом, что дублирование дескриптора также пропускает одну и ту же блокировку). Следовательно, возможно, что несколько процессов имеют одну и ту же исключительную консультативную блокировку flock() в том же файле на в то же время, если они получили дескриптор от создателя после вызова flock() .

Блокировка файлов является на удивление сложной проблемой. Я лично получил лучшие результаты, просто придерживаясь блокировки fcntl() . Семантика по. Блокировки fcntl() не являются самыми легкими в работе, и в некоторых случаях могут быть откровенно бешеными; просто я обнаружил, что он дает лучшие - самые надежные, самые портативные, наименее удивительные результаты.

    
ответ дан Nominal Animal 14.03.2014 в 18:09
  • Добавление к комментарию выше: Linux 2.6.12 был выпущен 18 июня 2005 года, так что даже во время ответа flock () работал над NFS. –  Akilan 16.05.2018 в 13:24
  • @Akilan: Какую часть? Не путайте flock () с lockf (); ужасно прокомментировать это, не указывая точно, что не так. Это похоже на то, что вы сделали ошибку, не указав на ошибку. Это не только бесполезно, но делает тон очень самодовольным и недружелюбным. Я считаю, что вы сами путаете lockf () и flock () в разделе NOTES. Что касается NFS и flock () на ядрах до 2.6.12, да, это заслуживает примечания, спасибо. –  Nominal Animal 16.05.2018 в 14:50
  • Мне жаль, что это было не очень ясно. Я действительно говорю о NFS. –  Akilan 17.05.2018 в 14:18
  • @ Акилан: Нет, это было ясно. Вы сказали: «Ответ уже не верен», но не указывал, как, или какая часть. Без дальнейших подробностей я должен не соглашаться, потому что, помимо упоминания версии ядра, я не вижу, как мой ответ отличается от справочной страницы вообще. –  Nominal Animal 17.05.2018 в 14:34
  • Вы правы. Я удалил комментарий. –  Akilan 17.05.2018 в 14:52
1

Наиболее вероятная причина условной компиляции заключается в том, что ни одна из двух функций не доступна на каждой платформе.

    
ответ дан NPE 14.03.2014 в 16:49
  • Это была моя первоначальная мысль, проверка показала, что они оба поддерживаются на платформах. Возможно, это не так исторически, так что это, кажется, фронтмен. –  Dan McGrath 14.03.2014 в 16:55