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

       

Вызов pause приостанавливает выполнение вызывающего


uses linux;
Procedure Pause;
Вызов pause приостанавливает выполнение вызывающего процесса (так что процесс при этом не занимает процессорного времени) до получения любого сигнала, например, сигнала SIGALRM. Если сигнал вызывает нормальное завершена процесса или игнорируется процессом, то в результате вызова pause будет просто выполнено соответствующее действие (завершение работы или игнорирована сигнала).
Следующая программа tml (сокращение от «tell me later» – напомнить позднее) использует оба вызова alarm и pause для вывода сообщения в течение заданного числа минут. Она вызывается следующим образом:
$ tml число_минут текст_сообщения
Например:
$ tml 10 время идти домой
Перед сообщением выводятся три символа
Ctrl+G (звуковые сигналы) для привлечения внимания пользователя. Обратите внимание на создание в программе tml фонового процесса при помощи вызова fork. Фоновый процесс выполняет работу, позволяя пользователю продолжать выполнение других задач.
 (* tml - программа для напоминания *)
{$mode objfpc}
uses linux, stdio, sysutils;
const


  BELLS=#7#7#7;   (* звуковой сигнал ASCII *)
  alarm_flag:boolean = FALSE;
(* Обработчик сигнала SIGALRM *)
procedure setflag(sig:integer);cdecl;
begin
  alarm_flag := TRUE;
end;
var
  nsecs, j:integer;
  pid:longint;
  act:sigactionrec;
begin
  if paramcount < 2 then
  begin
    writeln (stderr, 'Применение: tml число_минут сообщение');
    halt(1);
  end;
  try
    nsecs := strtoint(paramstr(1)) * 60;
  except
    on e:econverterror do
    begin
      writeln (stderr, 'Введено нечисловое значение');
      halt(2);
    end; 
  end;
  if nsecs <= 0 then
  begin
    writeln (stderr, 'tml: недопустимое время');
    halt(3);
  end;
  (* Вызов fork, создающий фоновый процесс *)
  pid := fork;
  case pid of
    -1:               (* ошибка *)
    begin
      perror ('tml');
      halt(1);
    end;
    0:                (* дочерний процесс *)


      ;
    else         (* родительский процесс *)
    begin
      writeln('Процесс tml с идентификатором ', pid);
      halt(0);
    end;
  end;
  (* Установить обработчик таймера *)
  act.handler.sh := @setflag;
  sigaction (SIGALRM, @act, nil);
  (* Установить таймер *)
  alarm (nsecs);
  (* Приостановить выполнение до получения сигнала ... *)
  pause;
  (* Если был получен сигнал SIGALRM, вывести сообщение *)
  if alarm_flag then
  begin
    write(BELLS);
    for j := 2 to paramcount do
      write(paramstr(j),' ');
    writeln;
  end;
  halt(0);
end.
Из этого примера можно получить представление о том, как работает подпрограмма sleep, вызывая вначале
alarm, а затем pause.
Упражнение 6.3. Напишите свою версию подпрограммы sleep. Она должна сохранить предыдущее состояние таймера и восстанавливать его при выходе. (Посмотрите полное описание процедуры sleep в справочном руководстве системы.)
Упражнение 6.4. Перепишите программу tml, используя свою версию процедуры sleep.

Содержание раздела