1283 — I have exclusive access
1284 — Lock already present
В приведенном примере показано, как взаимодействуют две выполняющиеся копии одной и той же программы. Если вы попробуете выполнить данный пример, то почти наверняка увидите другие идентификаторы процессов в выводе, но поведение программ будет тем же самым.
Как это работает
Для демонстрации вы 10 раз выполняете в программе цикл с помощью оператора while
Поскольку это всего лишь пример, вы ждете очень короткий промежуток времени. Когда программа завершает использование ресурса, она снимает блокировку, удаляя файл с блокировкой. Далее она может выполнить другую обработку (в данном случае это просто функция sleep
Важно уяснить, что это совместное мероприятие, и вы должны корректно писать программы для его работы. Программа, потерпевшая неудачу в создании файла с блокировкой, не может просто удалить файл и попробовать снова, Возможно, в дальнейшем она сумеет создать файл с блокировкой, но у другой программы, уже создавшей такой файл, нет способа узнать о том, что она лишилась исключительного доступа к ресурсу.
Блокировка участков файла
Создание файлов с блокировкой подходит для управления исключительным доступом к ресурсам, таким как последовательные порты или редко используемые файлы, но этот способ не годится для доступа к большим совместно используемым файлам. Предположим, что у вас есть большой файл, написанный одной программой и одновременно обновляемый многими программами. Такая ситуация может возникнуть, если программа записывает какие-то данные, получаемые непрерывно или в течение длительного периода, и обрабатывает их с помощью нескольких разных программ. Обрабатывающие программы не могут ждать, пока программа, записывающая данные, завершится — она работает постоянно, поэтому программам нужен какой-то способ кооперации для обеспечения одновременного доступа к одному и тому же файлу.
Урегулировать эту ситуацию можно, блокируя участки файла. При этом конкретная часть файла блокируется, но другие программы могут иметь доступ к другим участкам файла. Это называется
fcntl
или системного вызова lockf
. Мы рассмотрим интерфейс fcntl
, поскольку он наиболее часто применяется. Интерфейс lockf
в основном аналогичен, и в ОС Linux он используется как альтернативный интерфейсу fcntl
. Однако блокирующие механизмы fcntl
и lockf
не работают вместе: у них разные низкоуровневые реализации. Поэтому никогда не следует смешивать вызовы этих двух типов; выберите один или другой.Вы встречали вызов fcntl в
#include
int fcntl(int fildes, int command, ...);
Системный вызов fcntl
command
, может выполнять разные задачи. Для блокировки файлов интересны три приведенные далее возможные значения параметра command:F_GETLK
F_SETLK
F_SETLKW
Когда вы используете эти варианты, третий аргумент в вызове должен быть указателем на структуру struct flock
int fcntl(int fildes, int command, struct flock *flock_structure);
Структура flock
short l_type
short l_whence
off_t l_start
off_t l_len
pid_t l_pid
Элемент l_type