Системное программирование в UNIX средствами Free Pascal




Клинч - часть 2


(* Программа deadlock - демонстрация клинча *)

uses linux, stdio;

var

  fd:longint;

  first_lock, second_lock:flockrec;

begin

  first_lock.l_type := F_WRLCK;

  first_lock.l_whence := SEEK_SET;

  first_lock.l_start := 0;

  first_lock.l_len := 10;

  second_lock.l_type := F_WRLCK;

  second_lock.l_whence := SEEK_SET;

  second_lock.l_start := 10;

  second_lock.l_len := 5;

  writeln(sizeof(flockrec));

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

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

  if linuxerror>0 then  (*A *)

    fatal ('A');

  writeln ('A: успешная блокировка (процесс ',getpid,')');

  case fork of

    -1:

      (* ошибка *)

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

    0:

    begin

      (* дочерний процесс *)

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

      if linuxerror>0 then    (*B *)

        fatal ('B');

      writeln ('B: успешная блокировка (процесс ',getpid,')');

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

      if linuxerror>0 then    (*C *)

        fatal ('C');

      writeln ('C: успешная блокировка (процесс ',getpid,')');

      halt (0);

    end;

    else

    begin

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

      writeln ('Приостановка родительского процесса');

      sleep (10);

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

      if linuxerror>0 then    (*D *)

        fatal ('D');

      writeln ('D: успешная блокировка (процесс ',getpid,')');

    end;

  end;

end.

Вот пример работы этой программы:

А: успешная блокировка (процесс 1410)

Приостановка родительского процесса

В: успешная блокировка (процесс 1411)

D: Deadlock situation detected/avoided

С: успешная блокировка (процесс 1411)

В данном случае попытка блокировки завершается неудачей в точке /*D*/, и процедура perror выводит соответствующее системное сообщение об ошибке. Обратите внимание, что после того, как родительский процесс завершит работу и его блокировки будут сняты, дочерний процесс сможет выполнить вторую блокировку.

Это пример использует процедуру fatal, которая была применена в предыдущих главах.

Упражнение 8.1. Напишите процедуры, выполняющие те же действия, что и вызовы fdread и fdwrite, но которые завершатся неудачей, если уже установлена блокировка нужного участка файла. Измените аналог вызова fdread так, чтобы он блокировал читаемый участок. Блокировка должна сниматься после завершения вызова fdread.

Упражнение 8.2. Придумайте и реализуйте условную схему блокировок нумерованных логических записей файла. (Совет: можно блокировать участки файла вблизи максимально возможного смещения файла, даже если там нет данных. Блокировки в этом участке файла могут иметь особое значение, например, каждый байт может соответствовать определенной логической записи. Блокировка в этой области может также использоваться для установки различных флагов.)




Содержание  Назад  Вперед