Скачиваний:
63
Добавлен:
08.01.2014
Размер:
2.6 Mб
Скачать

Установка блокировки при помощи вызова fcntl

Следующий пример показывает, как можно использовать вызов fcntl для установления блокировки записи.

uses linux,stdio;

.

.

.

var

my_lock:flockrec;

my_lock.l_type := F_WRLCK;

my_lock.l_whence := SEEK_CUR;

my_lock.l_start := 0;

my_lock.l_len := 512;

fcntl (fd, F_SETLKW, longint(@my_lock));

При этом будут заблокированы 512 байт, начиная с текущего положения указателя чтения-записи. Заблокированный участок теперь считается «зарезервированным» для исключительного использования процессом. Информация о блокировке помещается в свободную ячейку системной таблицы блокировок.

Если весь участок файла или какая-то его часть уже были заблокированы другим процессом, то вызывающий процесс будет приостановлен до тех пор, пока не будет доступен весь участок. Приостановка работы процесса может быть прервана при помощи сигнала; в частности, для задания времени ожидания может быть использован вызов alarm. Если ожидание не будет прервано, и, в конце концов, участок файла освободится, то процесс заблокирует его. Если происходит ошибка, например, если вызову fcntl передается неверный дескриптор файла или переполнится системная таблица блокировок, то будет возвращено значение -1.

Следующий пример – программа lockit открывает файл с именем locktest (который должен существовать) и блокирует его первые десять байт при помощи вызова fcntl. Затем она порождает дочерний процесс, пытающийся заблокировать первые пять байт файла; родительский процесс в это время делает паузу на пять секунд, а затем завершает работу. В этот момент система автоматически снимает блокировку, установленную родительским процессом.

(* Программа lockit - блокировка при помощи вызова fcntl *)

uses linux,stdio;

var

fd:integer;

my_lock:flockrec;

begin

(* Установка параметров блокировки записи *)

my_lock.l_type := F_WRLCK;

my_lock.l_whence := SEEK_SET;

my_lock.l_start := 0;

my_lock.l_len := 10;

(* Открыть файл *)

fd := fdopen ('locktest', Open_RDWR);

(* Заблокировать первые десять байт *)

fcntl (fd, F_SETLKW, longint(@my_lock));

if linuxerror > 0 then

begin

perror ('parent: locking');

halt (1);

end;

writeln('Родительский процесс: блокировка установлена');

case fork of

-1: (* ошибка *)

begin

perror ('Ошибка вызова fork');

halt (1);

end;

0:

begin

my_lock.l_len := 5;

fcntl (fd, F_SETLKW, longint(@my_lock));

if linuxerror > 0 then

begin

perror ('Дочерний процесс: установка блокировки');

halt (1);

end;

writeln ('Дочерний процесс: блокировка установлена');

writeln ('Дочерний процесс: выход');

halt (0);

end;

end;

(* родительский процесс *)

sleep (5);

(* Выход, который автоматически снимет блокировку. *)

writeln ('Родительский процесс: выход');

halt (0);

end.

Вывод программы lockit может выглядеть примерно так:

Родительский процесс: блокировка установлена

Родительский процесс: выход

Дочерний процесс: блокировка установлена

Дочерний процесс: выход

Обратите внимание на порядок, в котором выводятся сообщения. Он показывает, что дочерний процесс не может наложить блокировку до тех пор, пока родительский процесс не завершит работу и не снимет тем самым блокировку, в противном случае сообщение Дочерний процесс: блокировка установлена появилось бы вторым, а не третьим. Этот пример показывает, что блокировка, наложенная родительским процессом, также затронула и дочерний, хотя блокируемые участки файла и не совсем совпадали. Другими словами, попытка блокировки завершится неудачей, даже если участок файла лишь частично перекрывает уже заблокированный. Эта программа иллюстрирует несколько интересных моментов. Во-первых, блокировка информации не наследуется при вызове fork; дочерний и родительский процессы в данном примере выполняют блокировку независимо друг от друга. Во-вторых, вызов fcntl не изменяет положение указателя чтения-записи файла – во время выполнения обоих процессов он указывает на начало файла. В-третьих, все связанные с процессом блокировки автоматически снимаются при его завершении.

Соседние файлы в папке Полищук, Семериков. Системное программирование в UNIX средствами Free Pascal