В чем разница между блокировкой с `fcntl` и` flock`?

Я читаю часами, но не могу понять, что такое разница между двумя блокировками. Единственное, что я понимаю, это то, что блокировка fcntl() предлагает гранулированную блокировку, которая может блокировать определенные байты и что только fcntl() поддерживает блокировку NFS.

Он сказал, что разница в их семантике, как они себя ведут при дублировании dup() или while fork(), но я не могу понять, в чем разница на практике.

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

Ответ 1

Я попытался выяснить различия на основе имеющейся документации и сделал следующие выводы (пожалуйста, поправьте меня, если я ошибаюсь):

С помощью fcntl() (POSIX):

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

  • Если процесс замирает или закрывает любой файл filedescriptor в этот файл, запись блокировки удаляется системой.

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

  • просто: блокировки fnctl работают как отношение Process ↔ File, игнорируя filedescriptors

flock() (BSD) отличается (Linux: поскольку kernel 2.0, flock() реализуется как системный вызов самостоятельно, а не эмулируется в библиотеке GNU C в качестве вызова fcntl):

  • flock() создает блокировки в системах "Открыть описания файлов". "Открытые описания файлов" генерируются вызовами open().

  • filedescriptor (FD) является ссылкой на "Описание открытого файла". FD, сгенерированные dup() или fork(), относятся к тому же "Open file description".

  • процесс может генерировать несколько "открытых описаний файлов" для одного файла, открыв() файл несколько раз

  • flock() помещает его через FD в "Открыть описание файла"

  • поэтому flock() может использоваться для синхронизации доступа к файлам между процессами, а также потоков (в одном или нескольких процессах).

  • см. flock (2) и особенно open (2 ) man details for "Open files description".

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

Если вам нужна синхронизация между несколькими потоками, возможно, в нескольких процессах, вы должны использовать блокировки на основе flock(), если ваша система поддерживает их без эмуляции с помощью fcntl(). Затем каждый поток должен открывать() файл, а не использовать ручки dup() ed или fork() ed.