• Поле si_value содержит данные, указанные в аргументе value (объединение sigval) процессом, пославшим сигнал с помощью функции sigqueue().

• Поля si_pid и si_uid содержат соответственно идентификатор процесса и реальный идентификатор пользователя процесса, отправившего сигнал.

В листинге 22.3 приводится пример обработки сигналов реального времени. Программа перехватывает сигналы и выводит на экран значения различных полей структуры siginfo_t, передаваемой ей обработчиком сигнала. Программа принимает два необязательных целочисленных аргумента командной строки.

Если указан первый аргумент, то программа блокирует все сигналы и затем переходит в режим сна на количество секунд, указанное в этом аргументе. В это время мы можем поставить в очередь к процессу несколько сигналов реального времени и пронаблюдать, что произойдет, когда сигналы будут разблокированы. Второй аргумент задает количество секунд, на протяжении которых обработчик сигнала должен оставаться в режиме сна перед возвратом управления. Указание ненулевого значения (значение по умолчанию 1) может быть полезным для замедления работы программы с тем, чтобы мы могли более четко увидеть, что происходит, когда обрабатываются несколько сигналов.

Мы можем использовать программу из листинга 22.3 вместе с программой из листинга 22.2 (t_sigqueue.c) для изучения поведения сигналов реального времени, как показано в следующем журнале сессии оболочки:

$ ./catch_rtsigs 60 &

[1] 12842

$ ./catch_rtsigs: PID is 12842 Приглашение оболочки и вывод программы смешались

./catch_rtsigs: signals blocked — sleeping 60 seconds

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

$ ./t_sigqueue 12842 54 100 3 Отправить сигнал трижды

./t_sigqueue: PID is 12843, UID is 1000

$ ./t_sigqueue 12842 43 200

./t_sigqueue: PID is 12844, UID is 1000

$ ./t_sigqueue 12842 40 300

./t_sigqueue: PID is 12845, UID is 1000

Со временем программа catch_rtsigs выходит из режима сна и начинает выводить на печать сообщения по мере того, как обработчик перехватывает различные сигналы. (На экране мы видим, что приглашение оболочки смешивается с программным выводом. Это происходит потому, что программа catch_rtsigs распечатывает информацию из фонового режима.) Мы видим, что сигналы реального времени с меньшим номером доставляются первыми, а также что структура siginfo_t, передаваемая обработчику, содержит PID и UID процесса, пославшего сигнал:

$ ./catch_rtsigs: sleep complete

caught signal 40

si_signo=40, si_code=–1 (SI_QUEUE), si_value=300

si_pid=12845, si_uid=1000

caught signal 43

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

si_pid=12844, si_uid=1000

Оставшийся вывод производится тремя экземплярами одного и того же сигнала реального времени. Просмотрев значения поля si_value, мы можем увидеть, что эти сигналы были доставлены в том же порядке, в котором они были отправлены:

caught signal 54

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

si_pid=12843, si_uid=1000

caught signal 54

si_signo=54, si_code=–1 (SI_QUEUE), si_value=101

si_pid=12843, si_uid=1000

caught signal 54

si_signo=54, si_code=–1 (SI_QUEUE), si_value=102

si_pid=12843, si_uid=1000

Далее мы воспользуемся командой оболочки kill для отправки сигнала в программу catch_rtsigs. Как и раньше, мы увидим, что структура siginfo_t, получаемая обработчиком, включает идентификатор процесса и идентификатор (имя) пользователя процесса, пославшего сигнал, однако в этом случае значение поля si_code — константа SI_USER:

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

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

12780

$ kill -40 12842 Использует kill(2) для отправки сигнала

$ caught signal 40

si_signo=40, si_code=0 (SI_USER), si_value=0

si_pid=12780, si_uid=1000 PID совпадает с идентификатором оболочки

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

$ kill 12842 Завершить catch_rtsigs отправкой SIGTERM

Caught 6 signals

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

[1]+ Done./catch_rtsigs 60

Листинг 22.3. Обработка сигналов реального времени

signals/catch_rtsigs.c

#define _GNU_SOURCE

#include

#include

#include "tlpi_hdr.h"

static volatile int handlerSleepTime;

static volatile int sigCnt = 0; /* Количество полученных сигналов */

static volatile int allDone = 0;

static void /* Обработчик для сигналов, установленных с SA_SIGINFO */

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

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