ВУЗ:
Составители:
25
int
main (void)
{
signal (SIGALRM, catch_alarm);
alarm (2);
while (keep_going)
do_stuff ();
return EXIT_SUCCESS;
}
Обработчики второго типа обычно используются для выполнения некоторых
завершающих действий при критических ошибках. Наилучший путь для прекращения
выполнения процесса – вызвать тот же сигнал с определенным действием по
умолчанию. Например,
volatile sig_atomic_t fatal_error_in_progress = 0;
void
fatal_error_signal (int sig)
{
if (fatal_error_in_progress)
raise (sig);
fatal_error_in_progress = 1;
...
signal (sig, SIG_DFL);
raise (sig);
}
Если запущен обработчик для конкретного сигнала, то этот сигнал блокируется
до тех пор, пока работа обработчика не будет завершена. Тем не менее, работа
обработчика может быть прервана приходом какого-либо другого сигнала. Для того,
чтобы избежать этого нужно использовать поле sa_mask структуры sigaction, чтобы
указать какие сигналы будут заблокированы в процессе выполнения обработчика.
При написании обработчиков сигналов следует стремиться к минимизации его
кода и сокращению времени выполнения. Критическим местом могут стать структуры
данных, с которыми работает обработчик. Необходимо придерживаться следующих
принципов:
• если обработчику необходимо работать с глобальной переменной,
определенной в программе, то она должна быть определена как volatile, что
говорит компилятору о возможности изменения ее асинхронно;
• если в обработчике вызывается какая-либо функция, убедитесь, что она
является повторно входимой или в том, что сигнал не может прервать
выполнение этой функции.
Элементарный доступ к данным
При написании обработчиков существует проблема обращения к
неэлементарным данным (объектам в памяти, доступ к которым может быть
осуществлен лишь при выполнении нескольких операций с данными). В случае
поступления сигнала в момент модификации содержимого объекта, его значение может
стать непредсказуемым. Например,
#include <signal.h>
#include <stdio.h>
int
main (void)
{
signal (SIGALRM, catch_alarm);
alarm (2);
while (keep_going)
do_stuff ();
return EXIT_SUCCESS;
}
Обработчики второго типа обычно используются для выполнения некоторых
завершающих действий при критических ошибках. Наилучший путь для прекращения
выполнения процесса – вызвать тот же сигнал с определенным действием по
умолчанию. Например,
volatile sig_atomic_t fatal_error_in_progress = 0;
void
fatal_error_signal (int sig)
{
if (fatal_error_in_progress)
raise (sig);
fatal_error_in_progress = 1;
...
signal (sig, SIG_DFL);
raise (sig);
}
Если запущен обработчик для конкретного сигнала, то этот сигнал блокируется
до тех пор, пока работа обработчика не будет завершена. Тем не менее, работа
обработчика может быть прервана приходом какого-либо другого сигнала. Для того,
чтобы избежать этого нужно использовать поле sa_mask структуры sigaction, чтобы
указать какие сигналы будут заблокированы в процессе выполнения обработчика.
При написании обработчиков сигналов следует стремиться к минимизации его
кода и сокращению времени выполнения. Критическим местом могут стать структуры
данных, с которыми работает обработчик. Необходимо придерживаться следующих
принципов:
• если обработчику необходимо работать с глобальной переменной,
определенной в программе, то она должна быть определена как volatile, что
говорит компилятору о возможности изменения ее асинхронно;
• если в обработчике вызывается какая-либо функция, убедитесь, что она
является повторно входимой или в том, что сигнал не может прервать
выполнение этой функции.
Элементарный доступ к данным
При написании обработчиков существует проблема обращения к
неэлементарным данным (объектам в памяти, доступ к которым может быть
осуществлен лишь при выполнении нескольких операций с данными). В случае
поступления сигнала в момент модификации содержимого объекта, его значение может
стать непредсказуемым. Например,
#include
#include
25
Страницы
- « первая
- ‹ предыдущая
- …
- 23
- 24
- 25
- 26
- 27
- …
- следующая ›
- последняя »
