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

51.3.9. Зависание блокировок и приоритет отложенных запросов на их получение

Когда несколько процессов вынуждены ждать своей очереди, чтобы установить блокировку для участка, уже кем-то заблокированного, возникает несколько вопросов.

Может ли процесс, пытающийся установить блокировку для записи, зависнуть из-за других процессов, которые устанавливают блокировки для чтения того же участка? В Linux (как и во многих других реализациях UNIX) это действительно может произойти, вызывая зависание блокировки для записи (возможно, даже навсегда).

Существуют ли какие-либо правила очередности получения блокировок в ситуации, когда их пытаются установить сразу несколько процессов? Например, выдаются ли они по принципу «первым пришел — первым ушел»? И зависят ли эти правила от типа блокировки, запрашиваемой каждым из процессов (то есть имеют ли блокировки для чтения приоритет перед блокировками для записи или наоборот)? В Linux действуют такие правила:

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

• записывающие блокировки не имеют приоритета перед считывающими и наоборот.

Эти утверждения могут оказаться неактуальными в других системах. В некоторых реализациях UNIX запросы на получение блокировок обслуживаются по принципу «первым пришел — первым ушел», а чтение имеет более высокий приоритет по сравнению с записью.

51.4. Строгая блокировка

Блокировки, которые мы обсуждали до сих пор, являлись необязательными. Это значит, что процесс может выполнять обычный ввод/вывод, не прибегая к вызову fcntl() (или flock()). Ядро не сможет помешать возникновению подобной ситуации. При использовании необязательных блокировок приложение само должно:

• установить для файла подходящего владельца (или группу) и права доступа, чтобы не дать неизвестному процессу выполнять для файла ввод/вывод;

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

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 не поддерживает бит установки группового идентификатора, поэтому строгую блокировку в ней использовать нельзя.

Влияние строгой блокировки на операции ввода/вывода

Перейти на страницу:

Похожие книги