ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4276
Скачиваний: 28
Часть III. Стандартная библиотека языка программирования C
376
В результате работы этой программы на консоль будут выведены
следующие сообщения:
Long jump value: 0
Function is working
Long jump value: 10
Г Л А В А
32
Обработка исключительных
ситуаций <signal.h>
32.1. Сигналы
Сигналы служат для оповещения программы о следующих собы-
тиях:
во время исполнения программы произошла ошибка;
во время исполнения программы произошло асинхронное со-
бытие.
Например, ошибка может быть вызвана переполнением при опе-
рации над данными с плавающей точкой. В качестве примера
асинхронного события можно привести нажатие клавиши клавиа-
туры.
Все сигналы перенумерованы. В заголовочном файле signal.h оп-
ределены следующие символические константы для некоторых
предопределенных сигналов:
/* аварийное завершение посредством вызова функции abort */
#define SIGABRT const_int_выражение
/* ошибка в операции с плавающей точкой */
#define SIGFPE const_int_выражение
/* неправильная инструкция */
#define SIGILL const_int_выражение
/* прерывание */
#define SIGINT const_int_выражение
Часть III. Стандартная библиотека языка программирования C
378
/* ошибка доступа к памяти */
#define SIGSEGV const_int_выражение
/* сигнал на завершение программы */
#define SIGTERM const_int_выражение
Здесь
const_int_выражение
представляет собой выражение, ре-
зультатом вычисления которого является неотрицательное цело-
численное значение.
Для каждой реализации в заголовочном файле signal.h могут быть
определены и другие сигналы.
32.2. Установка функции
обработки сигнала
Для установки функции обработки сигнала предназначена функ-
ция
signal
, которая имеет следующий прототип:
void (* signal(int sig, void (*f)(int)))(int);
где параметр
sig
задает номер сигнала, для которого устанавли-
вается обработчик, заданный параметром
f
. Здесь
f
является ука-
зателем на функцию, которая имеет следующий прототип:
void f(int);
и часто называется
функцией обработки сигнала
или просто
об-
работчиком сигнала
. В случае успешного завершения функция
signal
возвращает указатель на предыдущую функцию, установ-
ленную для обработки этого сигнала, а в случае неудачи — зна-
чение, определенное макросом
SIG_ERR
.
Для максимальной переносимости программ рекомендуется, что-
бы обработчики асинхронных сигналов использовали только сле-
дующие возможности:
вызовы функции
signal
, которые успешно завершаются;
присваивание значений переменным типа
sig_atomic_t
;
возврат управления.
Тип
sig_atomic_t
определен в заголовочном файле signal.h и
предназначен для определения переменных, значения которых
Глава 32. Обработка исключительных ситуаций <signal.h>
379
изменяются атомарными операциями, т. е. такими операциями,
которые не прерываются во время своего исполнения. Определе-
ние типа
sig_atomic_t
обычно имеет следующий вид:
typedef int sig_atomic_t;
Переменные типа
sig_atomic_t
обычно имеют квалификатор
volatile
и используются для взаимодействия между функцией
обработки сигнала и программой.
Обработчик сигнала может завершить свое исполнение вызовом
функций
abort
,
exit
и
longjmp
.
В заголовочном файле signal.h определены макросы для следую-
щих стандартных обработчиков сигналов:
#define SIG_DFL const_адрес /* обработчик по умолчанию */
#define SIG_IGN const_адрес /* игнорирование сигнала */
Выражение
const_адрес
задает адрес стандартного обработчика
для сигнала. Чаще всего эти адреса являются просто целочислен-
ными константами, проверяя значения которых среда исполнения
выполняет некоторые действия при вызове соответствующего
обработчика.
В заголовочном файле signal.h могут быть также определены
макросы и для других обработчиков сигналов.
32.3. Возбуждение сигнала
Для возбуждения сигнала предназначена функция
raise
, которая
имеет следующий прототип:
int raise(int sig);
Эта функция возбуждает сигнал, номер которого задан парамет-
ром
sig
. В случае успешного завершения функция возвращает
значение
0
, а в случае неудачи — ненулевое значение.
Функция
raise
работает следующим образом. После возбуждения
сигнала управление передается функции обработки этого сигна-
ла. Функция
raise
не возвращает управление до тех пор, пока не
завершит свое исполнение функция обработки сигнала. Однако
Часть III. Стандартная библиотека языка программирования C
380
отметим, что после возврата управления из функции
raise
пове-
дение программы не определено, если обрабатывались сигналы
SIGFPE
,
SIGILL
или
SIGSEGV
. В этом случае для выхода из функции
обработки сигнала лучше использовать функцию
longjmp
.
При вызове функции обработки сигнала среда исполнения может
выполнять следующие действия:
блокировать повторное возбуждение сигнала с тем же номе-
ром, который обрабатывает функция обработки сигнала, до
передачи управления из этого обработчика;
для обработки повторного сигнала с тем же номером, который
обрабатывает функция обработки сигнала, вызвать обработчик
сигнала, заданный по умолчанию;
для повторного сигнала
SIGILL
среда исполнения может про-
должить обработку предыдущего такого сигнала.
В листинге 32.1 приведен пример использования функций
signal
и
raise
.
Листинг 32.1. Обработка сигнала
#include<signal.h>
#include<stdio.h>
void handler(int sig)
{
printf("Signal handler.\n");
}
int main()
{
void (*f)(int); /* указатель на обработчик */
/* запоминаем предыдущий обработчик */
f = signal(SIGINT, handler);
if(f == SIG_ERR)
{
printf("Signal set failed.\n"); // неудача
return 0;
}
printf("Raise signal.\n");