Ответ 1
Практическая разница между flock()
и lockf()
заключается в семантике (поведение по отношению к закрытию и прохождению), применимости к NFS и другим общим файловым системам, а также то, являются ли консультативные блокировки видимыми для других процессов с помощью fcntl()
блокировки или нет.
Библиотека, которую вы используете, просто имеет логику для выбора желаемой семантики на основе текущей платформы.
Если семантика (поведение над передачей дескриптора, forking и т.д.) приемлема, вы должны предпочесть lockf()
/fcntl()
блокировать блокировки flock()
в Linux, просто потому, что первая работает с файловыми системами NFS и т.д. в то время как последний нет. (В BSD и Mac OS X, я считаю, вам нужно явно использовать fcntl()
вместо этого.)
В Linux lockf()
это всего лишь оболочка fcntl()
, а flock()
блокировки являются отдельными (и будут работать только в локальных файловых системах, а не на примерах монтирования NFS). То есть, у одного процесса может быть эксклюзивная блокировка flock()
для файла, а другой процесс имеет эксклюзивную блокировку fcntl()
в этом же файле. Оба являются консультативными блокировками, но они не взаимодействуют.
В Mac OS X и FreeBSD, lockf()
/flock()
/fcntl()
блокировки всех взаимодействуют, хотя разработчикам рекомендуется использовать только один из интерфейсов в приложении. Однако только fcntl()
блокирует работу NFS mounts (и, очевидно, только если оба клиента и сервер NFS настроены на поддержку блокировок записей, что на удивление редко встречается в например, среды веб-хостинга, огромная причина головных болей для некоторых веб-разработчиков (каркасных) разработчиков).
В POSIX явно не указано, как блокировать блокировки lockf()
/flock()
/fcntl()
, а в прошлом были различия. Теперь ситуация немного успокоилась, и можно приблизительно сказать, что
-
fcntl()
блокировки являются наиболее надежнымиВо всех архитектурах они имеют наилучшие шансы работать прямо, например. общие файловые системы - например, NFS и CIFS.
-
Чаще всего
lockf()
реализуется как "стенография" дляfcntl()
Другая альтернатива, как "стенография" для
flock()
, возможна, но в настоящее время редкая. -
fcntl()
иflock()
имеют разную семантику wrt. наследование и автоматические релизыfcntl()
блокировки сохраняются вexec()
, но не наследуются черезfork()
. Блокировки освобождаются, когда процесс владения закрывает любой дескриптор, ссылаясь на тот же файл.В Linux, FreeBSD и MAc OS X блокировки
flock()
связаны с открытым файловым дескриптором: передача дескриптора также передает блокировку. (В man-страницах указано, что "блокировка находится в файле, а не в дескрипторе файла". Это не противоречие. Это просто означает, что блокировка применяется к файлу. Она по-прежнему связана с дескриптором таким образом что дублирование дескриптора также пропускает одну и ту же блокировку). Поэтому возможно, что несколько процессов имеют одну и ту же эксклюзивную консультативную блокировкуflock()
в том же файле одновременно, если они получили дескриптор от отправителя послеflock()
.
Блокировка файлов является на удивление сложной проблемой. Я лично получил лучшие результаты, просто придерживаясь fcntl()
блокировки. Семантика по. fcntl()
блокировки не являются самыми легкими в работе, и в некоторых случаях это может быть откровенно бесит; это просто то, что я нашел, что он дает лучшие - самые надежные, самые портативные, наименее удивительные результаты.