next up previous contents
Next: Посылка сигналов с помощью Up: Сигналы Previous: Сигналы   Contents

Понятие о сигналах

Сигналы являются программными прерываниями, которые посылаются процессу, когда случается некоторое событие. Сигналы могут возникать синхронно с ошибкой в приложении, например SIGFPE (ошибка вычислений с плавающей запятой) и SIGSEGV (ошибка адресации), но большинство сигналов является асинхронными. Сигналы могут посылаться процессу, если система обнаруживает программное событие, например, когда пользователь дает команду прервать или остановить выполнение, или получен сигнал на завершение от другого процесса. Сигналы могут прийти непосредственно от ядра ОС, когда возникает сбой аппаратных средств ЭВМ. Система определяет набор сигналов, которые могут быть отправлены процессу. В Linux применяется около 30 различных сигналов. При этом каждый сигнал имеет целочисленное значение и приводит к строго определенным действиям.

Механизм передачи сигналов состоит из следующих частей:

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

Известно три варианта реакции на сигналы:

Чтобы реагировать на разные сигналы, необходимо знать концепции их обработки. Процесс должен организовать так называемый обработчик сигнала в случае его прихода. Для этого используется функция signal():

#include <signal.h>

void(*signal(int signr, void(*sighandler)(int)))(int);

Такой прототип очень сложен для понимания. Следует упростить его, определив тип для функции обработки:

typedef void signalfunction(int);
После этого прототип функции примет вид:
signalfunction *signal(int signr,

      signalfunction *sighandler);

signr устанавливает номер сигнала, для которого устанавливается обработчик. В заголовочном файле <signal.h> определены следующие сигналы (табл. 1).

Таблица 1. Сигналы ОС Linux.


Номер Значение Реакция программы по умолчанию
SIGABRT Ненормальное завершение (abort()) Завершение
SIGALRM Окончание кванта времени Завершение
SIGBUS Аппаратная ошибка Завершение
SIGCHLD Изменение состояния потомка Игнорирование
SIGCONT Продолжение прерванной программы Продолжение / игнорирование
SIGEMT Аппаратная ошибка Завершение
SIGFPE Ошибка вычислений с плавающей запятой Завершение
SIGILL Неразрешенная аппаратная команда Завершение
SIGINT Прерывание с терминала Завершение
SIGIO Асинхронный ввод/вывод Игнорирование
SIGKILL Завершение программы Завершение
SIGPIPE Запись в канал без чтения Завершение
SIGPWR Сбой питания Игнорирование
SIGQUIT Прерывание с клавиатуры Завершение
SIGSEGV Ошибка адресации Завершение
SIGSTOP Остановка процесса Остановка
SIGTTIN Попытка чтения из фонового процесса Остановка
SIGTTOU Попытка записи в фоновый процесс Остановка
SIGUSR1 Пользовательский сигнал Завершение
SIGUSR2 Пользовательский сигнал Завершение
SIGXCPU Превышение лимита времени CPU Завершение
SIGXFSZ Превышение пространства памяти (4GB) Завершение
SIGURG Срочное событие Игнорирование
SIGWINCH Изменение размера окна Игнорирование

Переменная sighandler определяет функцию обработки сигнала. В заголовочном файле <signal.h> определены две константы SIG_DFL и SIG_IGN. SIG_DFL означает выполнение действий по умолчанию - в большинстве случаев - окончание процесса. Например, определение signal(SIGINT, SIG_DFL); приведет к тому, что при нажатии на комбинацию клавиш CTRL+C во время выполнения сработает реакция по умолчанию на сигнал SIGINT и программа завершится. С другой стороны, можно определить
signal(SIGINT, SIG_IGN);

Если теперь нажать на комбинацию клавиш CTRL+C, ничего не произойдет, так как сигнал SIGINT игнорируется. Третьим способом является перехват сигнала SIGINT и передача управления на адрес собственной функции, которая должна выполнять действия, если была нажата комбинация клавиш CTRL+C, например
signal(SIGINT, function);

Пример использования обработчика сигнала приведен ниже:

#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

 

void sigfunc(int sig) {

  char c;

  if(sig != SIGINT)

  return;

  else {

    printf("\nХотите завершить программу (y/n) : ");

    while((c=getchar()) != 'n')

    return;

    exit (0);

  }

}

int main() {

  int i;

  signal(SIGINT,sigfunc);

  while(1)

  {

    printf(" Вы можете завершить программу с помощью

            CTRL+C ");

    for(i=0;i<=48;i++)

    printf("\b");

  }

  return 0;

}


next up previous contents
Next: Посылка сигналов с помощью Up: Сигналы Previous: Сигналы   Contents
2004-06-22