./t_sigwaitinfo: PID is 3837

./t_sigwaitinfo: signals blocked

./t_sigwaitinfo: about to delay 60 seconds

[1] 3837

$ ./t_sigqueue 3837 43 100 Отправить сигнал 43

./t_sigqueue: PID is 3839, UID is 1000

$ ./t_sigqueue 3837 42 200 Отправить сигнал 42

./t_sigqueue: PID is 3840, UID is 1000

Со временем программа завершает период сна — и цикл с функцией sigwaitinfo() принимает поставленные в очередь сигналы. (На экране приглашения оболочки перемешаны с выводом программы, так как программа t_sigwaitinfo распечатывает вывод из фонового режима). Как и в случае с сигналами реального времени, перехваченными обработчиком, мы видим, что сигналы доставляются в порядке увеличения их номера, а также что структура siginfo_t, передаваемая обработчику сигнала, позволяет нам получить идентификатор процесса и идентификатор пользователя процесса, пославшего сигнал:

$ ./t_sigwaitinfo: finished delay

got signal: 42

si_signo=42, si_code=–1 (SI_QUEUE), si_value=200

si_pid=3840, si_uid=1000

got signal: 43

si_signo=43, si_code=–1 (SI_QUEUE), si_value=100

si_pid=3839, si_uid=1000

Мы продолжаем, используя команду оболочки kill для отправки сигнала в процесс. В этот раз мы увидим, что полю si_code присвоено значение SI_USER (вместо SI_QUEUE):

Нажмите Enter, чтобы увидеть следующее приглашение оболочки

$ echo $$ Отобразить PID оболочки

3744

$ kill — USR1 3837 Оболочка посылает SIGUSR1 с помощью kill()

$ got signal: 10 Доставка SIGUSR1

si_signo=10, si_code=0 (SI_USER), si_value=100

si_pid=3744, si_uid=1000 3744 — это PID оболочки

Нажмите Enter, чтобы увидеть следующее приглашение оболочки

$ kill %1 Завершить программу с помощью SIGTERM

$

Нажмите Enter, чтобы увидеть уведомление о завершении фоновой задачи

[1]+ Done./t_sigwaitinfo 60

В выводе для принятого сигнала SIGUSR1 мы видим, что полю si_value присвоено значение 100. Это то значение, с каким данное поле было инициализировано предшествующим сигналом, отправленным с помощью функции sigqueue(). Ранее отмечалось, что поле si_value содержит валидную информацию только для сигналов, посланных с помощью функции sigqueue().

Листинг 22.6. Синхронное ожидание сигналов с sigwaitinfo()

signals/t_sigwaitinfo.c

#define _GNU_SOURCE

#include

#include

#include

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

int sig;

siginfo_t si;

sigset_t allSigs;

if (argc > 1 && strcmp(argv[1], "-help") == 0)

usageErr("%s [delay-secs]\n", argv[0]);

printf("%s: PID is %ld\n", argv[0], (long) getpid());

/* Блокировать все сигналы (исключая SIGKILL и SIGSTOP) */

sigfillset(&allSigs);

if (sigprocmask(SIG_SETMASK, &allSigs, NULL) == –1)

errExit("sigprocmask");

printf("%s: signals blocked\n", argv[0]);

if (argc > 1) {

/* Пауза для того, чтобы сигналы могли быть отправлены нам */

printf("%s: about to delay %s seconds\n", argv[0], argv[1]);

sleep(getInt(argv[1], GN_GT_0, "delay-secs"));

printf("%s: finished delay\n", argv[0]);

}

for (;;) { /* Получать сигналы до SIGINT (^C) или SIGTERM */

sig = sigwaitinfo(&allSigs, &si);

if (sig == –1)

errExit("sigwaitinfo");

if (sig == SIGINT || sig == SIGTERM)

exit(EXIT_SUCCESS);

printf("got signal: %d (%s)\n", sig, strsignal(sig));

printf(" si_signo=%d, si_code=%d (%s), si_value=%d\n",

si.si_signo, si.si_code,

(si.si_code == SI_USER)? "SI_USER":

(si.si_code == SI_QUEUE)? "SI_QUEUE": "other",

si.si_value.sival_int);

printf(" si_pid=%ld, si_uid=%ld\n",

(long) si.si_pid, (long) si.si_uid);

}

}

signals/t_sigwaitinfo.c

Системный вызов sigtimedwait() — это вариация функции sigwaitinfo(). Единственное отличие заключается в том, что функция sigtimedwait() позволяет ограничить время ожидания.

#define _POSIX_C_SOURCE 199309

#include

int sigtimedwait(const sigset_t *set, siginfo_t *info,

const struct timespec *timeout);

Возвращает номер доставленного сигнала при успешном завершении или –1 при ошибке или тайм-ауте (EAGAIN)

Аргумент timeout устанавливает максимальное количество времени, на протяжении которого функция sigtimedwait() будет ожидать сигнал. Этот аргумент — это указатель на структуру следующего типа:

struct timespec {

time_t tv_sec; /* Секунды ('time_t' целочисленный тип) */

long tv_nsec; /* Наносекунды */

};

Перейти на страницу:

Похожие книги