9. Согласно POSIX сигналы, обработчики для которых также устанавливаются с флагом
SA_SIGINFO
, но не входящие в диапазон сигналов реального времени, например стандартные сигналы UNIX, могут обрабатываться как на основе помещения их в очередь, так и без ее использования; выбор оставляется на усмотрение разработчика ОС.
Мы перечислили основные требования POSIX к модели обработки сигналов реального времени. Дополнения, отличия и специфические структуры данных QNX будут рассмотрены немного позже.
Весьма доходчивый пример для проверки и иллюстрации обработки сигналов реального времени приведен У. Стивенсом [2]. Мы же построим приложение, реализующее его основную идею: [33]
Приоритеты сигналов реального времени
#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
#include <signal.h>
#include <unistd.h>
static void handler(int signo, siginfo_t* info, void* context) {
cout << "received signal " << signo << " code = " << info->si_code <<
" val = " << info->si_value.sival_int << endl;
}
int main(int argc, char *argv[]) {
cout << "signal SIGRTMIN=" << (int)SIGRTMIN
<< " - signal SIGRTMAX=" << (int)SIGRTMAX << endl;
int opt, val, beg = SIGRTMAX, num = 3,
fin = SIGRTMAX - num, seq = 3;
// обработка параметров запуска:
while ((opt = getopt(argc, argv, "b:e n")) != -1) {
switch(opt) {
case 'b': // начальный сигнал серии
if (sscanf(optarg, "%i", &val) != 1)
perror("parse command line failed"), exit(EXIT_FAILURE);
beg = val;
break;
case 'e': // конечный сигнал серии
if (sscanf(optarg, "%i", &val) != 1)
perror("parse command line failed"), exit(EXIT_FAILURE);
fin = val;
break;
case 'n': // количество сигналов в группе посылки
if (sscanf(optarg, "%i", &val) != 1)
perror("parse command line failed"), exit(EXIT_FAILURE);
seq = val;
break;
default:
exit(EXIT_FAILURE);
}
}
num = fin - beg;
fin += num > 0 ? 1 : -1;
sigset_t sigset;
sigemptyset(&sigset);
for (int i = beg; i != fin; i += (num > 0 ? 1 : -1))
sigaddset(&sigset, i);
pid_t pid;
// вот здесь ветвление на 2 процесса
if (pid - fork() == 0) {
// дочерний процесс, здесь будут приниматься посланные сигналы
sigprocmask(SIG_BLOCK, &sigset, NULL);
for (int i = beg; i != fin; i += (num > 0 ? 1 : -1)) {
struct sigaction act, oact;
sigemptyset(&act.sa_mask);
act.sa_sigaction = handler;
// вот оно - реальное время!
act.sa_flags = SA_SIGINFO;
if (sigaction(i, &act, NULL) < 0) perror("set signal handler: ");
}
cout << "CHILD: signal mask set" << endl;
sleep(3); // пауза для посылки сигналов родителем
cout << "CHILD: signal unblock" << endl;
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
sleep(3); // пауза для приема всех сигналов
exit(EXIT_SUCCESS);
}
// родительский процесс: отсюда будут посылаться сигналы
sigprocmask(SIG_BLOCK, &sigset, NULL);
// пауза для установки обработчиков дочерним процессом
sleep(1);
union sigval value;
for (int i = beg, i != fin; i += (num > 0 ? 1 : -1)) {
for (int j = 0; j < seq; j++) {
value.sival_int = j;
sigqueue(pid, i, value);
cout << "signal sent: " << i << " with val = " << j << endl;
}
}
cout << "PARENT: finished!' << endl;
exit(EXIT_SUCCESS);
}