Книга: Основы программирования в Linux
Блокировка участков файла
Разделы на этой странице:
Блокировка участков файла
Создание файлов с блокировкой подходит для управления исключительным доступом к ресурсам, таким как последовательные порты или редко используемые файлы, но этот способ не годится для доступа к большим совместно используемым файлам. Предположим, что у вас есть большой файл, написанный одной программой и одновременно обновляемый многими программами. Такая ситуация может возникнуть, если программа записывает какие-то данные, получаемые непрерывно или в течение длительного периода, и обрабатывает их с помощью нескольких разных программ. Обрабатывающие программы не могут ждать, пока программа, записывающая данные, завершится — она работает постоянно, поэтому программам нужен какой-то способ кооперации для обеспечения одновременного доступа к одному и тому же файлу.
Урегулировать эту ситуацию можно, блокируя участки файла. При этом конкретная часть файла блокируется, но другие программы могут иметь доступ к другим участкам файла. Это называется блокировкой сегментов или участков файла. У системы Linux есть (как минимум) два способа сделать это: с помощью системного вызова fcntl
или системного вызова lockf
. Мы рассмотрим интерфейс fcntl
, поскольку он наиболее часто применяется. Интерфейс lockf
в основном аналогичен, и в ОС Linux он используется как альтернативный интерфейсу fcntl
. Однако блокирующие механизмы fcntl
и lockf
не работают вместе: у них разные низкоуровневые реализации. Поэтому никогда не следует смешивать вызовы этих двух типов; выберите один или другой.
Вы встречали вызов fcntl в главе 3. У него следующее определение:
#include <fcntl.h>
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
(он англ. file lock) зависит от конкретной реализации, но, как минимум, она будет содержать следующие элементы:
? short l_type
;
? short l_whence
;
? off_t l_start
;
? off_t l_len
;
? pid_t l_pid
.
Элемент l_type
принимает одно из нескольких значений (табл. 7.1), определенных в файле fcntl.h.
Таблица 7.1.
Значение | Описание |
---|---|
F_RDLCK |
Разделяемая или совместная блокировка (блокировка на чтение). У разных процессов может быть разделяемая блокировка одних и тех же (или перекрывающихся) участков файла. Если у какого-либо процесса есть разделяемая блокировка, ни один процесс не сможет установить исключительную блокировку этого участка. Для получения совместной блокировки файл должен быть открыт с правом на чтение или на чтение/запись |
F_UNLCK |
Разблокировать. Применяется для снятия блокировок |
F_WRLCK |
Исключительная блокировка (или блокировка на запись). Только один процесс может установить исключительную блокировку на любой конкретный участок файла. После того как процесс установил такую блокировку, никакой другой процесс не сможет установить блокировку любого типа на этот участок файла. Для установки исключительной блокировки файл должен быть открыт с правом на запись или на чтение/запись |
Элементы l_whence
, l_start
и l_len
определяют участок файла, непрерывную область в байтах. Элемент l_whence
должен задаваться одним из следующих значений: SEEK_SET
, SEEK_CUR
, SEEK_END
(из файла unistd.h). Они соответствуют началу, текущей позиции или концу файла соответственно. Элемент l_whence
задает смещение для первого байта участка файла, определенного элементом l_start
. Обычно оно задается константой SEEK_SET
, поэтому l_start
отсчитывается от начала файла. Параметр l_len
содержит количество байтов в участке файла.
Параметр l_pid
применяется для указания процесса, установившего блокировку; см. следующее далее описание значения F_GETLK
параметра command
.
Для каждого байта в файле может быть установлена блокировка только одного типа в каждый конкретный момент времени и может быть либо разделяемой блокировкой, либо исключительной или блокировка может отсутствовать. Для системного вызова fcntl
существует совсем немного комбинаций значений команд и вариантов, поэтому рассмотрим их все по очереди.
Значение F_GETLK параметра command
Первое значение параметра command — F_GETLK
. Эта команда получает информацию о файле, который открыт fildes
(первый параметр в вызове). Она не пытается блокировать файл. В процессе вызова передаются сведения о типе блокировки, которую хотелось бы установить, и вызов fcntl
с командой F_GETLK
возвращает любую информацию, которая могла бы помешать установке блокировки.
Значения, используемые в структуре flock
, приведены в табл. 7.2.
Таблица 7.2
Значение | Описание |
---|---|
l_type |
Или F_RDLCK для разделяемой (только чтение) блокировки, или F_WRLCK для исключительной (на запись) блокировки |
l_whence |
Одно из значений: SEEK_SET , SEEK_CUR или SEEK_END LCK |
l_start |
Начальный байт интересующего вас участка файла |
l_len |
Количество байтов в интересующем вас участке файла |
l_pid |
Идентификатор процесса, удерживающего блокировку |
Процесс может применять вызов с командой F_GETLK
для определения текущего состояния блокировки участка файла. Он должен настроить структуру flock
, указав тип требуемой блокировки и определив интересующую его область файла. Вызов fcntl
возвращает в случае успешного завершения значение, отличное от -1. Если у файла уже есть блокировки, препятствующие установке требуемой блокировки, структура flock
обновляется соответствующими данными. Если блокировке ничто не мешает, структура flock
не изменяется. Если вызов с командой F_GETLK
не может получить информацию, он возвращает -1 для обозначения аварийного завершения.
Если вызов с командой F_GETLK
завершился успешно (т. е. вернул значение, отличное от -1), вызвавшее его приложение должно проверить, изменено ли содержимое структуры flock
. Поскольку значение l_pid
содержит идентификатор блокирующего процесса (если таковой найден), это поле очень удобно для того, чтобы проверить, изменялась ли структура flock
.
Значение F_SETLK параметра command
Эта команда пытается заблокировать или разблокировать участок файла, заданного fildes
. В табл. 7.3 приведены значения полей структуры flock
(отличающиеся от значений, применяемых командой F_GETLK
).
Таблица 7.3
Значение | Описание |
---|---|
l_type |
Одно из следующих: • F_RDLCK — для разделяемой или допускающей только чтение блокировки; • F_WRLCK — для исключительной или блокировки записи; • F_UNLCK — для разблокирования участка |
l_pid |
Не используется |
Как и в случае F_GETLK
, блокируемый участок определяется значениями элементов l_start
, l_whence
и l_len
структуры flock
. Если блокировка установлена, вызов fcntl
вернет значение, отличное от -1, при аварийном завершении возвращается -1. Вызов завершается немедленно.
Значение F_SETLKW параметра command
Команда F_SETLKW
аналогична команде F_SETLK
за исключением того, что при невозможности установки блокировки вызов будет ждать до тех пор, пока такая возможность не представится. После перехода в состояние ожидания вызов завершится только, когда блокировка будет установлена или появится сигнал. Сигналы мы обсудим в главе 11.
Все блокировки файла, установленные программой, автоматически очищаются, когда закрывается соответствующий дескриптор файла. То же самое происходит, когда программа завершается.
- Статистика по блокировкам
- Эффективная работа с временными файлами сортировки
- Единое имя файла параметров InterBase
- Параметры конфигурационного файла InterBase
- 13. Зарабатываем на своих файлах: файлообменники, загружаеми получаем процент за скачивание
- Листинг 15.11. Код для загрузки файла с Web-сервера
- Создание и открытие файла
- Управление файлами занятий
- Как изменить имя файла или папки?
- Как создавать комментарии к файлам?
- Что такое расширение файла? Откуда Windows знает, какой программой открывать файл?
- Как узнать, что обозначает неизвестное расширение файла?