потоков (из главного потока) потоковые функции, помимо устанавливания своих индивидуальных сигнальных масок (в точности так, как это показано выше в листинге «Чередование потоковых
сигналов»), размещают экземпляры собственных потоковых данных:
// Теперь поток может пользоваться данными *pdb, как и локальными!
// цикл ожидания приходящих сигналов:
while (true) pause;
}
Все потоки используют один и тот же обработчик для всех сигналов; он выполняет одни и те же действия, но над различными объектами данных. Над каким объектом данных выполнить действие, обработчик «узнает» из контекста потока, в котором он выполняется:
• Теперь, например из главного потока процесса (главный поток выбран для простоты - источником сигнала может быть произвольный поток, даже не этого процесса), требуемое действие вызывается возбуждением соответствующего сигнала:
sigqueue(getpid, SIGRTMIN + K, val);
Это только скелетная схема, но на ее основе можно строить развитые протоколы обработки данных (пример взят из работоспособного приложения).
За пределы POSIX: сигналы в сети
А теперь, «на закуску», посмотрим справочную информацию по системной команде
kill
(послать сигнал). Вы, должно быть, помните, что в QNX есть дополнительная возможность получить справку по любой команде системы, используя команду
# use <имя-команды>
. Более того, вы можете и в любое свое приложение встроить возможность получения интерактивной справки. Как это происходит, описано в [4]. Итак:
# use kill
kill - terminate or signal processes (POSIX)
kill [-signal_name|-signal_number] pid ...
kill -l
Options:
– signal_name Symbolic name of signal to send
– signal_number Integer representing a signal type
нас ожидает сюрприз, который мы выделили в показанном фрагменте жирным шрифтом. И говорит эта строка о том, что в системе QNX сигнал может посылаться процессу, работающему на любом узле сети QNET. И это совершенно естественно, если вспомнить промелькнувшее выше замечание из технической документации, что сигнал в QNX - это пульс, то есть один из видов сообщений микроядра.
Таким образом, системная команда QNX
kill
(именно системная — /bin/kill, в отличие от встроенной формы
kill
командных интерпретаторов, которые строго следуют традициям UNIX, как и предупреждает выделенная нами строка) имеет возможность посылать сигналы любому процессу в сети. Тем не менее при рассмотрении прототипов вызовов
kill
и
sigqueue
мы не находим и следа параметра, предоставляющего возможность определить удаленный процесс. Тогда каким образом это делает команда
kill
? Совершенно верно: используя вызов native QNX API, который выглядит так (этот вызов, как и многие другие, имеет две формы, вторая из которых является безопасной в много- поточной среде):
#include <sys/neutrino.h>
int SignalKill(uint32_t nd, pid_t pid,
int tid, int signo, int code, int value);
int SignalKill_r(uint32_t nd, pid_t pid, int tid, int signo,
int code int value);
где
nd
— дескриптор сетевого узла QNET, на котором будут разыскиваться
pid
и
tid
. Для посылки сигнала локальному процессу (потоку) можно для
nd
указать 0, но лучше — определенную системой константу