Описание функций Си

       

Signal



     signal

Функция Определяет действия по обработке сигналов.

Синтаксис #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.

Смотрите также 7,

Пример:

/* В этом примере загружается программа обработки сигнала, возникающего при нажатии 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 /* не активизир. */ }


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