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

Пример 1: перехват сигнала sigint

Этот пример демонстрирует, как можно перехватить сигнал, а также проясняет лежащий в его основе механизм сигналов. Программа sigex просто связывает с сигналом SIGINT функцию catchint, а затем выполняет набор операторов sleep и writeln. В данном примере определена структура act типа sigactionrec как глобальная, поэтому при инициализации структуры все поля, и в частности поле sa_flags обнуляются.

(* Программа sigex - демонстрирует работу sigaction *)

uses linux,stdio;

(* Простая функция для обработки сигнала SIGINT *)

procedure catchint (signo:integer);cdecl;

begin

writeln (#$a'сигнал CATCHINT: signo=', signo);

writeln ('сигнал CATCHINT: возврат'#$a);

end;

var

act,oact:sigactionrec;

mask:sigset_t;

begin

(* Определение процедуры обработчика сигнала catchint *)

(* Задание действия при получении сигнала SIGINT *)

act.handler.sh := @catchint;

(* Создать маску, включающую все сигналы *)

sigfillset (@mask);

act.sa_mask:=mask.__val[0];

(* До вызова процедуры sigaction сигнал SIGINT

* приводил к завершению процесса (действие по умолчанию)

*)

sigaction (SIGINT, @act, @oact);

(* При получении сигнала SIGINT управление

* будет передаваться процедуре catchint

*)

writeln ('вызов sleep номер 1');

sleep (1);

writeln ('вызов sleep номер 2');

sleep (1);

writeln ('вызов sleep номер 3');

sleep (1);

writeln ('вызов sleep номер 4');

sleep (1);

writeln ('Выход');

halt(0);

end.

Сеанс обычного запуска sigex будет выглядеть так:

$ sigex

Вызов sleep номер 1

Вызов sleep номер 2

Вызов sleep номер 3

Вызов sleep номер 4

Выход

Пользователь может прервать выполнение программы sigex, нажав клавишу прерывания задания. Если она была нажата до того, как в программе sigex была выполнена процедура sigaction, то процесс просто завершит работу. Если же нажать да клавишу прерывания после вызова sigaction, то управление будет передано функции catchint:

$ sigex

Вызов sleep номер 1

<прерывание> (пользователь нажимает на клавишу прерывания)

Сигнал CATCHINT: signo = 2

Сигнал CATCHINT: возврат

Вызов sleep номер 2

Вызов sleep номер 3

Вызов sleep номер 4

Выход

Обратите внимание на то, как передается управление из тела программы процедуре catchint. После завершения процедуры catchint, управление продолжится с точки, в которой программа была прервана. Можно попробовать прервать программу sigex и в другом месте:

$ sigex

Вызов sleep номер 1

Вызов sleep номер 2

<прерывание> (пользователь нажимает на клавишу прерывания)

Сигнал CATCHINT: signo = 2

Сигнал GATCHINT: возврат

Вызов sleep номер 3

Вызов sleep номер 4

Выход

Пример 2: игнорирование сигнала sigint

Для того чтобы процесс игнорировал сигнал прерывания SIGINT, все, что нужно для этого сделать – это заменить следующую строку в программе:

act.handler.sh := @catchint;

на

act.handler.sh := SIG_IGN;

После выполнения этого оператора нажатие клавиши прерывания будет безрезультатным. Снова разрешить прерывание можно так:

act.handler.sh := SIG_DFL;

sigaction (SIGINT, @act, nil);

Можно игнорировать сразу несколько сигналов, например:

act.handler.sh := SIG_IGN;

sigaction(SIGINT, @act, nil);

При этом игнорируются оба сигнала SIGINT и SIGQUIT. Это может быть полезно в программах, которые не должны прерываться с клавиатуры.

Некоторые командные интерпретаторы используют этот подход, чтобы гарантировать, что фоновые процессы не останавливаются при нажатии пользователем клавиши прерывания. Это возможно вследствие того, что игнорируемые процессом сигналы будут игнорироваться и после вызова ехес. Поэтому командный интерпретатор может вызвать sigaction для игнорирования сигналов SIGQUIT и SIGINT, а затем запустить новую программу при помощи вызова ехес.

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