Функция Определяет действия по обработке сигналов.
Синтаксис #include
void (*signal(int sig, void (*func)
(int sig [, int subcode])))(int);
Файл, содержащий signal.h
прототип
Описание signal определяет как реагировать на сигнал, с но-
мером sig. Вы можете загрузить свою программу об-
работки сигнала или использовать две предопреде-
ленные подпрограммы, описанные в signal.h.
Это следующие:
--------------------------------------------------
Номер ф-ции Значение
--------------------------------------------------
SIG_DFG Завершить выполнение программы
SIG_IGN Игнорировать сигнал этого типа
SIG_ERR Определяет ошибку, возвращае-
мую signal
--------------------------------------------------
Имеются предопределенные типы сигналов:
--------------------------------------------------
Тип сигнала Значение
--------------------------------------------------
SIGABRT Ненормальное завершение. Действие
по умолчанию эквивалентно
_exit(3).
SIGFPE Арифметическая ошибка, возникаю-
щая при делении на 0, неверной
операции и т.п. Действие по
умолчанию эквивалентно _exit(1).
SIGILL Неверная операция. Действие
по умолчанию эквивалентно
_exit(1).
SIGINT Прерывание по Ctrl-C. Действие
по умолчанию INT 23H.
SIGSEGV Неверное обращение к памяти.
Действие по умолчанию экви-
валентно _exit(1).
SIGTERM Требование завершения программы.
Действие по умолчанию экви-
валентно _exit(1).
--------------------------------------------------
В signal.h определен тип, названный sig_atomic_t,
максимальный целый тип, который процессор может
автоматически запоминать при асинхронном прерыва-
нии (для семейства 8086 это 16-ти битовое слово,
целое значение для Turbo C++).
Когда функцией raise генерируется сигнал и в слу-
чае внешнего события, то присходит следующее:
1. Если загружена программа пользователя для об-
работки этого сигнала, то действие для сигнала
устанавливается в SIG_DFL.
2. Вызывается подпрограмма пользователя для обра-
ботки этого сигнала.
Подпрограмма пользователя может завершаться прос-
тым return или abort, _exit, exit или longjmp.
В Turbo C++ введено расширение стандарта ANSI C,
для сигналов типов SIGFPE, SIGSEGV и SIGILL.
Пользовательская функция обработки сигнала вызы-
вается с двумя или одним дополнительными парамет-
рами. Если с помощью raise был выдан сигнал
SIGFPE, SIGSEGV или SIGILL, то функция вызывается
с одним дополнительным параметром, целым, опреде-
ляющим что программа обработки сигнала вызвана.
Точные активизационные значения для этих сигналов
следующие (определены в float.h):
--------------------------------------------------
Тип сигнала Активизационное значение
--------------------------------------------------
SIGFPE FPE_EXPLICITGEN
SIGSEGV SEGV_EXPLICITGEN
SIGILL ILL__EXPLICITGEN
--------------------------------------------------
Если вызывается SIGSPE при появлении исключитель-
ной ситуации связанной с операциями над числами с
плавающей точкой, то подпрограмма пользователя
вызывается с дополнительным параметром определяю-
щим FPE_xxx тип сигнала. Если вызываеются сигналы
SIGILL, SIGSEGV или целочисленный вариант SIGFPE
(FPE_INTOVFLOW или FPE_INTDIV0), в результате ис-
ключительной ситуации процессора, то программа
обработки сигнала, определнная пользователем, вы-
зывается с двумя параметрами:
1. Тип исключительной ситуации SIGFPE, SIGSEGV
или SIGILL (смотри float.h, в котором приве-
денв все типы). Первый параметр это обычный
тип сигнала, определенный в ANSI C.
2. Целый указатель на программы обработки преры-
вания, которая вызвала эту программу обработки
сигналов. Он указывает на список регистров
процессора, которые были сохранены при возник-
новении исключительной ситуации. Регистры сох-
раняют в том же порядке, что и параметры прог-
рамм обработки прерываний: BP, DI, SI, DS, ES,
DX, CX, BX, AX, IP, CS, FLAGS. Для изменения
содержимого регистра при возврате управления,
измените значение в этом списке. К примеру,
для получения нового значения SI сделайте при-
мерно следующее:
*((int*)list_pointer+2) = new_SI_value
Таким образом вы получаете доступ к регистрам.
(Смотри пример 2).
Могут возникнуть или быть сгенерированы следующие
типы сигналов. Они соответствуют исключительным
ситуациям, которые может распознавать 8087, типа
"Деление целого на 0" и "переполнение при преры-
вании". Они объявлены в файле float.h
--------------------------------------------------
Сигнал SIGFPE Значение
--------------------------------------------------
FPE_INTOVFLOW Запущен INTO с установленным
флагом OF
FPE_INTDIV0 Деление целого на 0
FPE_INVALID Неверная операция
FPE_ZERODIVADE Деление на 0
FPE_UNDERFLOW Выход за нижнюю границу
FPE_OVERFLOW Переполнение
FPE_INEXACT Точность
FPE_EXPLICITGEN Запускается программа пользова-
теля raise(SIGFPE)
--------------------------------------------------
Замечание: сигналы FPE_INTOVFLOW и FPE_INTDIV0
генерируются при целочисленных операциях, а ос-
тальные при операциях над числами с плавающей
точкой. Исключительные ситуации при работе с чис-
лами с плавающей точкой генерируются в зависимос-
ти от слова управления сопроцессором, которое
можно изменить с помощью _control87. Ненормальные
ситуации обрабатываются Turbo C++ и не передаются
программе обработки сигналов.
Могут появиться следующие сигналы SIGSEGV:
--------------------------------------------------
Сигнал SIGSEGV Значение
--------------------------------------------------
SEGV_BOUND Выход за границы
SEGV_EXPLICITGEN вызвана raise(SIGSEGV)
--------------------------------------------------
Замечание: Процессоры 8088 и 8086 не имеют коман-
ды bound. 186, 286, 386 и NEC V серии имеют эту
команду. Т.о. при работе с 8088 и 8086 сигнал
SEGV_BOUND возникнуть не может. Turbo C++ не ис-
пользует эти команды, однако они могут появиться
во встроенном коде или в ассемблерных подпрограм-
мах, с которыми ваша программа компонуется.
Могут возникнуть следующие сигналы SIGILL:
--------------------------------------------------
Сигнал SIGILL Значение
--------------------------------------------------
ILL_EXECUTION Попытка неверной операции
ILL_EXPLICITGEN вызов raise(SIGILL)
--------------------------------------------------
Замечание: 8088, 8086, NEC V20 и NEC V30 не имеют
исключительной ситуации по неверной инструкции.
186, 286, 386, NEC V40 и NEC V50 имеют эту ситуа-
цию. Т.о. при работе с процессорами 8088, 8086,
NEC V20 и NEC V30 сигнал типа ILL_EXECUTION воз-
никнуть не может.
Замечание. Если тип сигнала SIGFPE, SIGSEGV или
SIGILL, то возврат из программы обработки сигнала
не желателен, т.к. состояние 8087 нарушено, ре-
зультат целочисленного деления неверен, возникло
переполнение, граничная операция ошибочна, или
была попытка выполнить несуществующую операцию.
Возврат может происходить только в том случае,
если программа обработки сигналов изменила регис-
тры так, что существует корректный контекст возв-
рата, или если сигнал был генерирован с помощью
raise, напрмер FPE_EXPLICITGEN, SEGV_EXPLICITGEN
или ILL_EXPLICITGEN. В основном, в этом случае
нужно печатать сообщение и завершать выполнение
программы с помощью _exit, exit или abort. Если
возврат осуществляется при другом состоянии, то в
этом случае результаты дальнейшей работы програм-
мы непредсказуемы.
Возвращаемое При успешном завершении signal возвращае указатель
значение на старую программу обработки сигнала для данного
типа сигналов. При ошибке signal возвращает
SIG_ERR и присваивает переменной errno значение
EINVAR.
Переносимость signal поддерживается стандартом ANSI C.
Смотрите также abort_control7, ctrlbrkexitlongjmpraisesetjmp
Пример:
/* В этом примере загружается программа обработки
сигнала, возникающего при нажатии Ctrl-Break */
#include
#include
#include
void Cather(int sig)
{
printf("\n Теперь программа обработки Break");
exit(1);
}
int main(void)
{
signal(SIGINT,Cather);
for(;;)
printf("\n Сейчас основная программа \n");
}
Пример 2:
/* В этом примере загружается программа обработки
сигналов SIGFPE, которая отлавливает состояние
переполнения при выполнении целочисленных опе-
раций, восстанавливает нормальное значение в
АХ и возвращает управление */
#pragma inline
#include
#include
void Catcher(int sig, int type, int *reglist)
{
printf("Поймал!\n");
*(reglist+8)=3; /* AX = 3 */
}
int main(void)
{
signal(SIGFPE,Catcher);
asm mov ax,07FFFH /* AX = 32767 */
asm inc ax /* вызвать перепол-
нение */
asm into /* активизировать
программу */
/* при возврате управления программа обработки
сигнала заносит в AX значение 3. Если этого не
сделать, то в следующей операции опять вызовет
into (после dec) */
asm dec ax /* нет перепол. */
asm into /* не активизир. */
}