В случае с вызовом flock() блокировка связывается только с дескриптором открытого файла и продолжает существовать, пока ее вручную не снимут или не будут закрыты все дескрипторы, ссылающиеся на описание открытого файла.
51.3.9. Зависание блокировок и приоритет отложенных запросов на их получение
Когда несколько процессов вынуждены ждать своей очереди, чтобы установить блокировку для участка, уже кем-то заблокированного, возникает несколько вопросов.
Может ли процесс, пытающийся установить блокировку для записи, зависнуть из-за других процессов, которые устанавливают блокировки для чтения того же участка? В Linux (как и во многих других реализациях UNIX) это действительно может произойти, вызывая зависание блокировки для записи (возможно, даже навсегда).
Существуют ли какие-либо правила очередности получения блокировок в ситуации, когда их пытаются установить сразу несколько процессов? Например, выдаются ли они по принципу «первым пришел — первым ушел»? И зависят ли эти правила от типа блокировки, запрашиваемой каждым из процессов (то есть имеют ли блокировки для чтения приоритет перед блокировками для записи или наоборот)? В Linux действуют такие правила:
• порядок, в котором удовлетворяются отложенные запросы, является неопределенным. Если несколько процессов ожидают своей очереди для установки блокировки, порядок их выполнения зависит от планировщика ядра;
• записывающие блокировки не имеют приоритета перед считывающими и наоборот.
Эти утверждения могут оказаться неактуальными в других системах. В некоторых реализациях UNIX запросы на получение блокировок обслуживаются по принципу «первым пришел — первым ушел», а чтение имеет более высокий приоритет по сравнению с записью.
Блокировки, которые мы обсуждали до сих пор, являлись
• установить для файла подходящего владельца (или группу) и права доступа, чтобы не дать неизвестному процессу выполнять для файла ввод/вывод;
• убедиться в том, что процессы, из которых состоит приложение, взаимодействуют друг с другом, получая перед выполнением ввода/вывода подходящие блокировки.
Linux, как и многие другие реализации UNIX, позволяет делать блокировки записей, создаваемые вызовом fcntl(),
Режим необязательной блокировки иногда называют дискреционным, а строгий режим — принуждающим. Строгая блокировка не предусмотрена стандартом SUSv3, но доступна в большинстве современных UNIX-систем (с рядом отличий в реализации).
Чтобы задействовать строгую блокировку в Linux, ее нужно сначала включить на уровне файловой системы, в которой хранятся интересующие файлы. Для этого систему следует подключить, используя параметр — o mand (доступный только в Linux):
# mount — o mand /dev/sda10 /testfs
Внутри программы того же результата можно добиться с помощью флага MS_MANDLOCK при вызове mount(2) (см. подраздел 14.8.1).
Чтобы проверить, подключена ли файловая система с поддержкой строгой блокировки, можно проанализировать вывод команды mount(8), запущенной без параметров:
# mount | grep sda10
/dev/sda10 on /testfs type ext3 (rw,mand)
Строгая блокировка файла становится возможной, когда бит установки группового идентификатора включен, а групповое выполнение, наоборот, выключено. В старых UNIX-системах такое сочетание битов с правами доступа ничего не значило и попросту игнорировалось. Это позволило включать строгую блокировку без необходимости переписывания существующих программ или добавления новых системных вызовов. В командной оболочке данный вид блокировки можно включить следующим образом:
$ chmod g+s,g-x /testfs/file
Чтобы сделать то же самое в программе, файлу нужно назначить походящие права доступа, воспользовавшись вызовом hmod() или fchmod() (см. подраздел 15.4.7).
При выполнении команды ls(1) для файла, для которого была включена строгая блокировка, в столбце с правами доступа, касающимися группового выполнения, будет указано значение S:
$ ls — l /testfs/file
— rw-r-Sr- 1 mtk users 0 Apr 22 14:11 /testfs/file
Строгая блокировка поддерживается всеми стандартными системами в Linux и UNIX, однако ее сопровождение может отсутствовать в некоторых сетевых файловых системах или системах, не относящихся к семейству UNIX. Например, система VFAT компании Microsoft не поддерживает бит установки группового идентификатора, поэтому строгую блокировку в ней использовать нельзя.