Весьма доходчивый пример для проверки и иллюстрации обработки сигналов реального времени приведен У. Стивенсом [2]. Мы же построим приложение, реализующее его основную идею: [33] Повторить приложение У. Стивенса в QNX в чистом виде не удастся — оно аварийно завершится по сигналу. Тонкий анализ этого факта интересен сам по себе, но он выходит за рамки нашего рассмотрения. Мы обращаем внимание на это обстоятельство, чтобы лишний раз сделать акцент на достаточно ощутимых отличиях реализаций QNX от схем POSIX (или того, как эти схемы понимаются в других ОС).
Приоритеты сигналов реального времени
#include
#include
#include
#include
#include
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);
}
Идея этого теста крайне проста:
• Создаются два процесса, один из которых (родительский) посылает серию последовательных (по номерам) сигналов, а второй (дочерний) должен их принять и обработать.
• Начальный и конечный номера сигналов в серии могут быть переопределены ключами -b
и -е
соответственно.
• Посылается не одиночный сигнал, а их повторяющаяся группа; размер группы повторений может быть переопределен ключом - n
.
• В качестве значения, передаваемого с каждым сигналом, устанавливается последовательный номер его посылки в группе.
Таким образом, мы можем изменять последовательность сигналов на передаче и наблюдать последовательность их доставки к принимающему процессу. Запустим полученное приложение и сразу же командой pidin
посмотрим его состояние:
1077295 1 ./s5 10r NANOSLEEP
1081392 1 ./s5 10r NANOSLEEP
Это то, что мы и предполагали получить. Рассмотрим теперь результат выполнения приложения со значениями сигналов по умолчанию (сигналы 56...54, именно в порядке убывания, в каждой группе посылается 3 сигнала):
# ./s5
signal SIGRTMIN=41 - signal SIGRTMAX=56
CHILD: signal mask set
signal sent: 56 with val = 0
signal sent: 56 with val = 1
signal sent: 56 with val = 2
signal sent: 55 with val = 0
signal sent: 55 with val = 1
signal sent: 55 with val = 2
signal sent: 54 with val = 0
signal sent: 54 with val = 1
signal sent: 54 with val = 2
PARENT: finished!
# CHILD: signal unblock
received signal 56 code = -2 val = 0
Читать дальше
Конец ознакомительного отрывка
Купить книгу