}
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