Unetway

C ++ - Обработка сигналов

Сигналы - это прерывания, передаваемые процессу операционной системой, которые могут прервать программу преждевременно. Вы можете сгенерировать прерывания, нажав Ctrl + C в системе UNIX, LINUX, Mac OS X или Windows.

Есть сигналы, которые не могут быть пойманы программой, но есть следующий список сигналов, которые вы можете поймать в своей программе и можете принимать соответствующие действия на основе сигнала. Эти сигналы определены в файле заголовка C ++ <csignal>.

SIGABRT

Аномальное завершение программы, например, вызов прерывания .

SIGFPE

Ошибочная арифметическая операция, такая как деление на ноль или операция, приводящая к переполнению.

SIGILL

Обнаружение незаконной инструкции.

SIGINT

Получение сигнала интерактивного внимания.

SIGSEGV

Недействительный доступ к хранилищу.

SIGTERM

Запрос завершения, отправленный в программу.

Функция signal()

Библиотека управления сигналами C ++ предоставляет signal() функции для обнаружения неожиданных событий. Ниже приведен синтаксис функции signal()

void (*signal (int sig, void (*func)(int)))(int); 

Сохраняя это просто, эта функция получает два аргумента: первый аргумент как целое число, которое представляет номер сигнала и второй аргумент как указатель на функцию обработки сигналов.

Напишем простую программу на C ++, где мы будем захватывать сигнал SIGINT, используя функцию signal(). Независимо от сигнала, который вы хотите поймать в своей программе, вы должны зарегистрировать этот сигнал с помощью функции signal() и связать его с обработчиком сигналов. Изучите следующий пример -

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler( int signum ) {
   cout << "Interrupt signal (" << signum << ") received.\n";

   // cleanup and close up stuff here  
   // terminate program  

   exit(signum);  
}

int main () {
   // register signal SIGINT and signal handler  
   signal(SIGINT, signalHandler);  

   while(1) {
      cout << "Going to sleep...." << endl;
      sleep(1);
   }

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он производит следующий результат:

Going to sleep....
Going to sleep....
Going to sleep....

Теперь нажмите Ctrl + c, чтобы прервать программу, и вы увидите, что ваша программа поймает сигнал и выйдет, напечатав что-то следующим образом:

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

Функция raise ()

Вы можете генерировать сигналы функцией raise(), которая принимает целочисленный номер сигнала в качестве аргумента и имеет следующий синтаксис.

int raise (signal sig);

Здесь sig - это номер сигнала для отправки любого из сигналов: SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGHUP. Ниже приведен пример, когда мы поднимаем сигнал внутренне с помощью функции raise() следующим образом:

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler( int signum ) {
   cout << "Interrupt signal (" << signum << ") received.\n";

   // cleanup and close up stuff here  
   // terminate program  

   exit(signum);  
}

int main () {
   int i = 0;
   // register signal SIGINT and signal handler  
   signal(SIGINT, signalHandler);  

   while(++i) {
      cout << "Going to sleep...." << endl;
      if( i == 3 ) {
         raise( SIGINT);
      }
      sleep(1);
   }

   return 0;
}

Когда приведенный выше код скомпилирован и исполнен, он производит следующий результат и выйдет автоматически:

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.