Приведем несколько небольших и самых простых примеров использования модели надежных сигналов.
Модель надежных сигналов
1. Перехватчик сигнала SIGINT
(реакция на пользовательский ввод [Ctrl+C]) [32] Инициализации, используемые в примерах вида sigaction act = { &catchint, 0, (sigset_t)0}; , будут зависимыми от системы из-за описанных ранее различий определения struct sigaction в разных ОС UNIX.
( файл s8.cc ):
void catchint(int signo) {
cout << "SIGINT: signo = " << signo << endl;
}
int main() {
static struct sigaction act = { &catchint, 0, (sigset_t)0 };
// запрещаем любые сигналы на время обработки SIGINT:
sigfillset(&(act.sa_mask));
// до этого вызова реакцией на Ctrl+C будет завершение задачи:
sigaction(SIGINT, &act, NULL);
for (int i = 0; i < 20; i++)
sleep(1), cout << "Cycle # " << i << endl;
}
Результатом нормального (без вмешательства оператора) выполнения приложения будет последовательность из 20 циклов секундных ожиданий, но если в процессе этих ожиданий пользователь пытается прервать работу процесса по [Ctrl+C], то он получит вывод, подобный следующему:
...
Cycle # 10
... здесь пользователь пытается прервать программу
SIGINT: signo = 2
Cycle # 11
...
2. Запрет прерывания выполнения программы с терминала. Для этого достаточно заменить строку инициализации структуры sigaction
на:
static struct sigaction act = { SIG_IGN, 0, (sigset_t)0 };
Можно проигнорировать сразу несколько сигналов (прерывающих выполнение программы с клавиатуры):
sigaction(SIGINT, &act, NULL );
sigaction(SIGQUIT, &act, NULL);
Далее остановимся еще на одном вызове API-сигналов, который широко используется в этой и последующих моделях обработки (сигналы реального времени, реакция в потоках):
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
Этот вызов позволяет прочитать текущее значение (если set
установлено в NULL
, то параметр how
игнорируется) или переустановить сигнальную маску для текущего потока. Параметры вызова:
• set
— это то значение, в соответствии с которым корректируется сигнальная маска процесса;
• how
— указывает, какое именно действие переустановки сигнальной маски требуется осуществить:
• SIG_BLOCK
— добавить сигналы, указанные в set к маске процесса (заблокировать реакцию на эти сигналы);
• SIG_UNBLOCK
— сбросить указанные set сигналы в сигнальной маске;
• SIG_SETMASK
— переустановить сигнальную маску процесса на значение, указанное в set
.
• oset
— значение, в котором будет сохранено значение маски, предшествующее вызову (старое значение).
Как и большинство сигнальных функций, данная функция возвращает нулевое значение в результате успешного выполнения и -1 в случае неудачи, при этом код ошибки устанавливается в errno
.
Именно эта функция снимает одно из самых существенных ограничений, свойственных модели «ненадежных сигналов», — позволяет заблокировать реакцию на сигналы при выполнении критических участков кода и восстановить ее при завершении выполнения этих участков.
Модель сигналов реального времени
Сигналы реального времени были добавлены в POSIX относительно недавно (1996 г.). Эта новая модель в различных ОС UNIX реализуется с разной степенью полноты и с отклонениями от спецификаций, и QNX не исключение. Модель еще до конца не отработана, поэтому возможны сюрпризы (и сейчас они будут).
Модель сигналов реального времени, которую специфицирует POSIX, устанавливается флагом SA_SIGINFO
(который уже упоминался выше) при вызове sigaction()
. В нижеследующем перечислении того, что предусматривает эта модель, мы излагаем в первую очередь качественную картину происходящего, предлагаемую POSIX, кое-где уточняя ее конкретными данными реализации QNX (артефакты в поведении QNX будут отдельно отмечены позже):
1. Сигналы, называемые сигналами реального времени, могут принимать значения между SIGRTMIN
и SIGRTMAX
. Количество таких сигналов определяется в системе константой RTSIG_MAX
, которая должна быть не менее 8 (POSIX). В QNX: SIGRTMIN
= 41, SIGRTMAX
= 56.
2. Обработка сигналов реального времени строится на основе очереди. Если сигнал порожден N раз, то он должен быть и N раз получен адресатом (в описываемых ранее моделях это не так, в них процесс получает только единичный экземпляр сигнала). Повторные экземпляры одного и того же сигнала в модели реального времени доставляются обработчику в порядке FIFO.
Читать дальше
Конец ознакомительного отрывка
Купить книгу