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

Flock vs lockf на Linux

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

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

4b9b3361

Ответ 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() блокировки не являются самыми легкими в работе, и в некоторых случаях это может быть откровенно бесит; это просто то, что я нашел, что он дает лучшие - самые надежные, самые портативные, наименее удивительные результаты.

Ответ 2

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