При активизации обязательного блокирования системные вызовы read()
и write()
блокируются, если они конфликтуют с уже установленными блокировками. Если процесс пытается осуществить запись в часть файла, на которой имеется блокировка чтения или записи от другого процесса, первый процесс блокируется до тех пор, пока существующая блокировка не будет снята. Подобным же образом вызовы read()
блокируются на областях, включенных в обязательные блокировки записи.
Обязательное блокирование записи приводит к большей потере производительности, чем рекомендательное блокирование, поскольку каждый вызов read()
и write()
должен быть проверен на предмет конфликтов с блокировками. Оно также не настолько переносимо, как рекомендательное блокирование POSIX, поэтому в большинстве приложений обязательное блокирование применять не следует.
13.3.4. Аренда файла
И рекомендательное, и обязательное блокирование предназначены для предотвращения доступа процесса к файлу или его части, которая используется другим процессом. Когда блокировка установлена, процесс, которому необходим доступ к файлу, должен подождать завершения процесса, владеющего блокировкой. Эта структура подходит для большинства применений, но иногда программа использует файл до тех пор, пока он не понадобится другой программе, и желает получить при необходимости эксклюзивный доступ к файлу. Для этого Linux предлагает механизм аренды файлов (в других системах это называется периодическими блокировками (oplocks))[93].
Взятие файла в аренду позволяет процессу получать уведомления (через сигнал) о доступе к файлу со стороны другого процесса. Существуют два типа аренды: аренда чтения и аренда записи. Аренда чтения вызывает передачу сигнала при открытии файла для записи, открытии с указанием O_TRUNC
или вызове truncate()
. Аренда записи также посылает сигнал при открытии файла для чтения[94]22. Аренды файлов работают только для модификаций, внесенных в файл той же системой, которая владеет арендой. Если файл локальный (не файл, доступ к которому возможен через сеть), любой подходящий доступ к файлу инициирует сигнал. Если доступ к файлу возможен через сеть, передачу сигнала вызывают только процессы на одной машине с процессо-арендатором; доступ с любой другой машины удается в случае отсутствия аренды.
Системный вызов fcntl()
используется для создания, реализации и запроса аренды файлов. Аренды можно размещать только на обычных файлах (для каналов и каталогов это невозможно), кроме того, аренды записи предоставляются только владельцу файла. Первый аргумент fcntl()
— это интересующий для слежения файловый дескриптор, а второй аргумент, command
, определяет, какую операцию следует выполнить.
F_SETLEASE
Аренда создается или освобождается в зависимости от значения последнего параметра, передаваемого в fcntl()
; F_RDLCK
создает аренду чтения, F_WRLCK
— аренду записи, a F_UNLCK
освобождает любую аренду, которая может существовать. Если запрашивается новая аренда, она заменяет любую существующую аренду. В случае ошибки возвращается отрицательное число; ноль или положительное число свидетельствуют об успехе операции[95].
F_GETLEASE
Возвращается тип аренды, существующей в настоящий момент для файла (F_RDLCK
, F_WRLCK
или F_UNLCK
).
Когда в арендованном файле происходит одно из контролируемых событий, ядро передает сигнал удерживающему аренду процессу. По умолчанию передается SIGIO
, но процесс может выбрать, какой сигнал передавать этому файлу, с помощью вызова fcntl()
, в котором второй параметр установлен в F_SETSIG
, а последний — в сигнал, который должен использоваться вместо SIGIO
.
Использование F_SETSIG
дает один значительный эффект. По умолчанию siginfo_t
не передается обработчику при доставке SIGIO
. Если используется F_SETSIG
, даже когда сигналом, передаваемым в ядро, является SIGIO
, a SA_SIGINFO
был установлен при регистрации обработчика сигнала, файловый дескриптор, аренда которого инициировала событие, передается в обработчик сигналов одновременно с элементом siginfo_t
по имени si_fd
. Это позволяет применять отдельный сигнал к аренде множества файлов, в то время как si_fd
сообщает сигналу, какому файлу необходимо уделить внимание[96].