Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org
Сигнал - программное прерывание , посылаемое процессу . Операционка использует сигналы для получения отчета в случае возникновения аварийных ситуаций . Это может быть указатель на неправильный адрес в памяти . Следующие события могут вызывать сигналы :
     1. Программные ошибки
     2. Нажатие клавиш Ctrl-C
     3. Срабатывание таймера 
     4. Вызов kill , raise 
События , которые генерят сигналы , можно разбить на 3 категории :
     1. Ошибки
     2. Внешние события
     3. Явный запрос
Не все программные ошибки генерят сигналы - например , открытие несуществующего сигнала не генерит сигнала . Внешние события связаны с I/O или многозадачностью . Явный запрос - это kill . Сигналы могут быть synchronously или asynchronously. Первые блокируют выполнение программы и обычно это программные ошибки . Каждый сигнал имеет свое адекватное действие , которое задокументировано . Для большинства сигналов это прекращение процесса . При этом сигнал пишет свой core dump file . Каждый сигнал определен как макрос , имеющий свое целочисленное значение .
 
  Группа программных сигналов :   
    int SIGFPE  - арифметическая ошибка
    int SIGILL  - invalid object , выход за границы массива и т.д.
    int SIGSEGV - выход за пределы доступной памяти
    int SIGBUS  - invalid pointer
    int SIGSYS  - bad system call
    
  Группа Termination Signals   
    int SIGTERM - в отличие от SIGKILL , его можно проигнорировать
    int SIGINT  - Ctrl-C
    int SIGQUIT - аналогичен SIGINT 
    int SIGKILL-немедленное прекращение процесса
    int SIGHUP  - сетевой разрыв
 
  Группа Alarm Signals
    int SIGALRM - вызов функции alarm
    int SIGVTALRM - CPU timer
    
  Группа  Asynchronous I/O Signals   
    int SIGIO  - файловый дескриптор готов к выполнению операций ввода-вывода
    int SIGURG - при появлении out-of-band данных в сокете
    
  Группа Job Control Signals     
    int SIGCHLD - посылается родительскому процессу дочерним при остановке
    int SIGCONT - сигнал на продолжение процесса
    int SIGSTOP - останавливает процесс
Для распечатки соответствующего сообщения нужно использовать функции strsignal и psignal. Следующий пример показывает , как удалить временный файл при возникновении сигнала :
  #include < signal.h >
  void termination_handler (int signum)
 {
   struct temp_file *p;
   for (p = temp_file_list; p; p = p->next)
     unlink (p->name);
 }
 intmain (void)
 {
   ...
     if (signal (SIGINT, termination_handler) == SIG_IGN) signal (SIGINT, SIG_IGN);
     if (signal (SIGHUP, termination_handler) == SIG_IGN) signal (SIGHUP, SIG_IGN);
     if (signal (SIGTERM, termination_handler) == SIG_IGN)signal (SIGTERM, SIG_IGN);
   ...
 }
Следующий пример показывает , как обработать программное прерывание в цикле :
  #include < signal.h >
  #include < stdio.h  >
  #include < stdlib.h >
  /* This flag controls termination of the main loop. */
  volatile sig_atomic_t keep_going = 1;
  /* The signal handler just clears the flag and re-enables itself. */
  void catch_alarm (int sig)
  {
    keep_going = 0;
    signal (sig, catch_alarm);
  }
  void  do_stuff (void)
    {
        puts ("Doing stuff while waiting for alarm....");
    }
        
 int main (void)
 {
   /* Establish a handler for SIGALRM signals. */
    signal (SIGALRM, catch_alarm);
   /* Set an alarm to go off in a little while. */
    alarm (2);
   /* Check the flag once in a while to see when to quit. */
    while (keep_going)
        do_stuff ();
      return EXIT_SUCCESS;
  }
 			 
 
В следующем примере родительский процесс порождает дочерний , который посылает родителю сигнал с использованием kill :
 #include < signal.h >
 #include < stdio.h >
 #include < sys/types.h >
 #include < unistd.h >
 
 /* When a SIGUSR1 signal arrives, set this variable. */
 volatile sig_atomic_t usr_interrupt = 0;
 void synch_signal (int sig)
 {
   usr_interrupt = 1;
 }
  /* The child process executes this function. */
  void child_function (void)
   {
     /* Perform initialization. */
     printf ("I'm here!!!  My pid is %d.\n", (int) getpid ());
     /* Let parent know you're done. */
     kill (getppid (), SIGUSR1);
     /* Continue with execution. */
       puts ("Bye, now....");
       exit (0);
   }
 int main (void)
  {
    struct sigaction usr_action;
    sigset_t block_mask;
    pid_t child_id;
    /* Establish the signal handler. */
    sigfillset (&block_mask);
    usr_action.sa_handler = synch_signal;
    usr_action.sa_mask = block_mask;
    usr_action.sa_flags = 0;
    sigaction (SIGUSR1, &usr_action, NULL);
    /* Create the child process. */
    child_id = fork ();
    if (child_id == 0)
    child_function ();          /* Does not return. */
    /* Busy wait for the child to send a signal. */
    while (!usr_interrupt) ;
    /* Now continue execution. */
    puts ("That's all, folks!");
    return 0;
  }
 
В следующем примере показана обработка сигналов в критической части кода с использованием sigprocmask:
  /* This variable is set by the SIGALRM signal handler. */
  volatile sig_atomic_t flag = 0;
  int main (void)
  {
    sigset_t block_alarm;
     ...
    /* Initialize the signal mask. */
    sigemptyset (&block_alarm);
    sigaddset (&block_alarm, SIGALRM);
    while (1)
    {
    /* Check if a signal has arrived; if so, reset the flag. */
     sigprocmask (SIG_BLOCK, &block_alarm, NULL);
     if (flag)
     {
          actions-if-not-arrived
          flag = 0;
     }
      sigprocmask (SIG_UNBLOCK, &block_alarm, NULL);
    ...
    }
  }   
  
Надежный способ блокировки сигналов - использование sa_mask в структуре sigaction :
 #include < signal.h >
 #include < stddef.h >
 void catch_stop ();
 void install_handler (void)
 {
   struct sigaction setup_action;
   sigset_t block_mask;
   sigemptyset (&block_mask);
   /* Block other terminal-generated signals while handler runs. */
   sigaddset (&block_mask, SIGINT);
   sigaddset (&block_mask, SIGQUIT);
   setup_action.sa_handler = catch_stop;
   setup_action.sa_mask = block_mask;
   setup_action.sa_flags = 0;
   sigaction (SIGTSTP, &setup_action, NULL);
 }
 
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье