Вызывающему процессу посылается сигнал, определенный
uses linux;
Procedure SigRaise(Sig:integer);
Вызывающему процессу посылается сигнал, определенный параметром sig и в случае успеха функция sigraise возвращает нулевое значение. Например:
uses Linux;
Var
oa,na : PSigActionRec;
Procedure DoSig(sig : Longint);cdecl;
begin
writeln('Receiving signal: ',sig);
end;
begin
new(na);
new(oa);
na^.handler.sh:=@DoSig;
na^.Sa_Mask:=0;
na^.Sa_Flags:=0;
na^.Sa_Restorer:=Nil;
SigAction(SigUsr1,na,oa);
if LinuxError<>0 then
begin
writeln('Error: ',linuxerror,'.');
halt(1);
end;
Writeln('Sending USR1 (',sigusr1,') signal to self.');
SigRaise(sigusr1);
end.
Вызов alarm – это простой и полезный вызов, который устанавливает таймер процесса. При срабатывании таймера процессу посылается сигнал.
uses linux;
Function Alarm(Secs:longint):Longint;
Переменная secs задает время в секундах, на которое устанавливается таймер. После истечения заданного интервала времени процессу посылается сигнал SIGALRM. Поэтому вызов
alarm(60);
приводит к посылке сигнала SIGALRM через 60 секунд. Обратите внимание, что вызов alarm не приостанавливает выполнение процесса, как вызов sleep, вместо этого сразу же происходит возврат из вызова alarm, и продолжается нормальное выполнение процесса, по крайней мере, до тех пор, пока не будет получен сигнал SIGALRM. Установленный таймер будет продолжать отсчет и после вызова ехec, но вызов fork выключает таймер в дочернем процессе.
Выключить таймер можно при помощи вызова alarm с нулевым параметром:
(* Выключить таймер *)
alarm(0);
Вызовы alarm не накапливаются: другими словами, если вызвать alarm дважды, то второй вызов отменит предыдущий. Но при этом возвращаемое вызовом alarm значение будет равно времени, оставшемуся до срабатывания предыдущего таймера, и его можно при необходимости записать.
Вызов alarm может быть полезен, если нужно ограничить время выполнения какого-либо действия. Основная идея проста: вызывается alarm, и процесс начинает выполнение задачи. Если задача выполняется вовремя, то таймер сбрасывается. Если выполнение задачи отнимает слишком много времени, то процесс прерывается при помощи сигнала SIGTERM и выполняет корректирующие действия.
Следующая функция quickreply использует этот подход для ввода данных от пользователя за заданное время. Она имеет один аргумент, приглашение командной строки, и возвращает указатель на введенную строку, или нулевой указатель, если после пяти попыток ничего не было введено. Обратите внимание, что после каждого напоминания пользователю функция quickreply посылает на терминал символ Ctrl+G. На большинстве терминалов и эмуляторов терминала это приводит к подаче звукового сигнала.
Функция quickreply вызывает процедуру gets из стандартной библиотеки ввода/вывода (Standard I/O Library). Процедура gets помещает очередную строку из стандартного ввода в массив char. Она возвращает либо указатель на массив, либо нулевой указатель в случае достижения конца файла или ошибки. Обратите внимание на то, что сигнал SIGALRM перехватывается процедурой обработчика прерывания catch. Это важно, так как по умолчанию получение сигнала SIGALRM приводит к завершению процесса. Процедура catch устанавливает флаг timed_out. Функция quickreply проверяет этот флаг, определяя таким образом, не истекло ли заданное время.
uses linux,stdio;
const
TIMEOUT=5; (* время в секундах *)
MAXTRIES=5; (* число попыток *)
LINESIZE=100; (* длина строки *)
CTRL_G=#7; (* ASCII символ звукового сигнала *)
var
(* Флаг, определяющий, истекло ли заданное время *)
timed_out:boolean;
(* Переменная, которая будет содержать введенную строку *)
answer:array [0..LINESIZE-1] of char;
(* Выполняется при получении сигнала SIGALRM *)
procedure catch (sig:integer);cdecl;
begin
(* Установить флаг timed_out *)
timed_out := TRUE;
(* Подать звуковой сигнал *)
write(CTRL_G);
end;
function quickreply(prompt:pchar):pchar;
var
ntries:integer;
act, oact:sigactionrec;
begin
(* Перехватить сигнал SIGALRM и сохранить старый обработчик *)
act.handler.sh := @catch;
sigaction (SIGALRM, @act, @oact);
for ntries:=1 to MAXTRIES do
begin
timed_out := FALSE;
writeln;
write(prompt, ' > ');
(* Установить таймер *)
alarm (TIMEOUT);
(* Получить введенную строку *)
gets (answer);
(* Выключить таймер *)
alarm (0);
(* Если флаг timed_out равен TRUE, завершить работу *)
if not timed_out then
break;
end;
(* Восстановить старый обработчик *)
sigaction (SIGALRM, @oact, nil);
(* Вернуть соответствующее значение *)
if ntries = MAXTRIES then
quickreply:=nil
else quickreply:=answer;
end;
begin
writeln;
writeln(quickreply ('Reply'));
end.