Системный вызов sigqueue() посылает сигнал реального времени, указанный в атрибуте sig, в процесс, указанный в атрибуте pid.
#define _POSIX_C_SOURCE 199309
#include
int sigqueue(pid_t
Возвращает 0 при успешном завершении, –1 при ошибке
Для отправки сигнала с помощью функции sigqueue() требуются те же разрешения, что и при использовании функции kill() (см. раздел 20.5). Можно отправить нулевой сигнал (то есть сигнал 0) — такая отправка несет тот же смысл, что и вызов kill(). (В отличие от функции kill() мы не можем вызвать функцию sigqueue() для отправки сигнала всей группе процессов, указав отрицательное значение параметра pid) (листинг 22.2).
Листинг 22.2. Использование функции sigqueue() для отправки сигнала реального времени
signals/t_sigqueue.c
#define _POSIX_C_SOURCE 199309
#include
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
int sig, numSigs, j, sigData;
union sigval sv;
if (argc < 4 || strcmp(argv[1], "-help") == 0)
usageErr("%s pid sig-num data [num-sigs]\n", argv[0]);
/* Отобразить наши PID и UID, чтобы их можно было сравнить с соответствующими
полями аргумента siginfo_t, передаваемого обработчику получающего процесса */
printf("%s: PID is %ld, UID is %ld\n", argv[0],
(long) getpid(), (long) getuid());
sig = getInt(argv[2], 0, "sig-num");
sigData = getInt(argv[3], GN_ANY_BASE, "data");
numSigs = (argc > 4)? getInt(argv[4], GN_GT_0, "num-sigs"): 1;
for (j = 0; j < numSigs; j++) {
sv.sival_int = sigData + j;
if (sigqueue(getLong(argv[1], 0, "pid"), sig, sv) == –1)
errExit("sigqueue %d", j);
}
exit(EXIT_SUCCESS);
}
signals/t_sigqueue.c
В аргументе value указываются данные, сопровождающие сигнал. Аргумент имеет такой вид:
union sigval {
int sival_int; /* Целочисленное значение для сопровождающих данных */
void *sival_ptr; /* Указатель для сопровождающих данных */
};
Интерпретация этого аргумента зависит от приложения, равно как и выбор, устанавливать ли значение поля sival_int или sival_ptr. Поле sival_ptr редко используется вместе с функцией sigqueue(), так как указатель, полученный в одном процессе, редко имеет какой-то смысл в другом. Однако это поле задействуется в других функциях, в которых применяются объединения sigval, как мы увидим при рассмотрении таймеров POSIX в разделе 23.6 и очередей сообщений POSIX в разделе 48.6.
В некоторых реализациях, в том числе Linux, в качестве синонима объединения sigval определяется тип данных sigval_t. Однако этот тип данных не указан в стандарте SUSv3 и может быть недоступен в некоторых реализациях. При создании переносимых приложений следует избегать использования этого типа данных.
Вызов функции sigqueue() может завершиться неудачей, если был достигнут предел количества сигналов реального времени в очереди. В этом случае errno присваивается значение EAGAIN, показывающее, что требуется повторная отправка сигнала (позже, когда хотя бы один из находящихся в очереди сигналов будет доставлен).
Пример использования функции sigqueue() приведен в листинге 22.2. Эта программа принимает до четырех аргументов, три первых из которых являются обязательными: идентификатор целевого процесса, номер сигнала, а также целое число, сопровождающее сигнал реального времени. Если требуется отправка нескольких экземпляров указанного сигнала, то можно воспользоваться четвертым, необязательным, аргументом для указания их количества. В этом случае сопровождающее целое число увеличивается на единицу для каждого последующего сигнала. Мы продемонстрируем выполнение этой программы в подразделе 22.8.2.
22.8.2. Обработка сигналов реального времени
Мы можем обрабатывать сигналы реального времени так же, как и стандартные сигналы: с помощью нормального обработчика с одним аргументом. Кроме того, мы также можем обрабатывать сигналы реального времени с помощью обработчика с тремя аргументами, устанавливаемого посредством флага SA_SIGINFO (см. раздел 21.4). Далее приведен пример использования флага SA_SIGINFO для установки обработчика шестого сигнала реального времени:
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_sigaction = handler;
act.sa_flags = SA_RESTART | SA_SIGINFO;
if (sigaction(SIGRTMIN + 5, &act, NULL) == –1)
errExit("sigaction");
При использовании флага SA_SIGINFO второй аргумент, передаваемый обработчику сигнала, — это структура siginfo_t, содержащая дополнительную информацию о сигнале реального времени. Детальное описание этой структуры приводится в разделе 21.4. Для сигнала реального времени в структуре siginfo_t устанавливаются значения следующих полей.
• Поле si_signo содержит значение, переданное в первом аргументе обработчика.
• Поле si_code обозначает источник сигнала и содержит одно из значений, перечисленных в табл. 21.2. Для сигнала реального времени, отправленного через функцию sigqueue(), это поле всегда имеет значение SI_QUEUE.