
Использование signal.H
Файл signal.h предоставляет стандартный механизм для простой обработки определяемых системой исключений. В этом файле определены исключения, представляющие собой целые значения, зависящие от системы. Вот некоторые примеры:
#define SIGINT 2 /сигнал прерывания/
#define SIGFPE 8 /исключение с плавающей точкой/
#define SIGABRT 22 /сигнал аварийного завершения/
Система может возбуждать (raise) эти исключения. Например нажатие на клавиатуре клавиш Ctr-C на многих системах генерирует прерывание, обычно убивающее текущий процесс.
Прототип функции raise() находится в файле signal.h, ее можно использовать для генерации явного исключения.
rize (SIGFPE); //возбужден сигнал исключения с плавающей точкой
Подобные исключения могут обрабатываться с помощью функции signal (). Она связывает обрабатывающую функцию с сигналом. Ее также можно использовать для игнорирования сигнала или для того, что бы заменить действие, выполняемое по умолчанию, на свою процедуру.
// вызвать my_abrt (), усли возбуждено SIGABRT
signal (SIGABRT, my_abrt);
// действовать по умолчанию, если возбуждено SIGABRT
signal (SIGABRT, SIG_DFL);
// игнорировать SIGFPE
signal (SIGFPE, SIG_IGN);
Подобные действия называются установкой (installing) обработчика(handler). Они заменяют обычные реакции системы обработчиком, определяемым пользователем.
Используем эти идеи для написания цикла, прерывание которого управляется с клавиатуры. После прерывания обработчик просит пользователя решить, должна ли программа продолжить выполнени.
В файле signal.Cpp
//Прерывания, обрабатываемые с помощью signal.h
#include <signal.h>
#include <time.h>
#include <iostream.h>
#include <stdlib.h>
void cntrl_c_handler (int sig);
inline double clk_psec()
{
return static_cast<double>(clock ())/CLOCKS_PER_SEC;
}
int main()
{
int i = 0, j;
cout << считаем до j миллионов, введите j: “;
cin >> j;
j = 1000000;
signal (SIGINT, cntrl_c_handler);
cout << clk_psec() << “начальное время \n”;
while (1) {
++i;
if (i>j) {
cout << clk_psec() << конец цикла \n;
cout << “ЦИКЛ ИСПОЛНЕН” <<j/1000000
<<”МИЛЛИОН РАЗ” << endl;
raise (SIGINT);
cout << “\nВведите j: ”;
cin >> j;
j =1000000;
I = 0;
cout << clk_psec() << начало цикла \n;
}
}
}
}
void cntrl_c_handler (int sig)
{
char c;
cout << “ПРЕРЫВАНИЕ”;
cout << “\nвведите Д для продолжения:”;
cin >> c:
if (c = =’Д’)
signal (SIGINT, cntrl_c_handler);
else
exit (0);
}
Разбор программы signal
-
signal (SIGINT, cntrl_c_handler);
Обработчик функции связан с прерыванием SIGINT. При выявлении следующего прерывания система вызывает cntrl_c_handler вместо системного действия по умолчанию.
-
while (1) {
++i;
if (i > j) {
….
raise (SIGINT);
Сигнал прерывания возбуждается явным вызовом; cntrl_c_handler() вызывается неявно.
-
void cntrl_c_handler (int sig)
Эта процедура обрабатывает исключение SIGINT.
-
cout << “ПРЕРЫВАНИЕ”;
cout << ”\nвведите Д для продолжения :”;
Было обнаружено прерывание и пользователю задается вопрос о том, что надо ли продолжать выполнение программы.
-
if (c = = ‘Д’)
signal (SIGINT, cntrl_c_handler);
По этому требованию продолжать выполнение обработчик исключений переустанавливается. Без этого система вернет обработчик прерываний к состоянию по умолчанию.
-
else
exit (0);
Для завершения вызывается функция exit () из stdlib.h.
Применим эту технику обработки исключений для типа vect (см.раздел 7.7, «Перегрузка операторов индексирования и присваивания», на стр.203). Начнем с замены проверки утверждений на условия, которые возбуждают определенные пользователем сигналы.