также позволяет сигналам, которые посылают программы, присоединять к себе один элемент данных (этот элемент может быть указателем, что позволяет неявно передавать любой необходимый объем данных). Чтобы отправить данные, используется
union sigval
.
#include <signal.h>
union sigval {
int sival_int;
void *sival_ptr;
};
Любой
из членов объединения —
sival_int
или
sival_ptr
— может быть установлен в требуемое значение, которое включается в
siginfo_t
, доставляемое вместе с сигналом. Чтобы сгенерировать сигнал с
union sigval
, должна использоваться функция
sigqueue
.
#include <signal.h>
void *sigqueue(pid_t pid, int signum, const union sigval value);
В отличие от
kill
,
pid
должен быть корректным идентификатором процесса (отрицательные значения не допускаются),
signum
указывает номер посылаемого сигнала. Подобно
kill
,
sigqueue
допускает нулевое значение
signum
нулю, чтобы проверить, позволяет ли вызывающий процесс посылать целевому сигналы, в действительности не выполняя такой посылки. Последний параметр,
value
, представляет собой элемент данных, передаваемый вместе с сигналом.
Чтобы принять
union sigval
, процесс, перехватывающий сигнал, должен использовать
SA_SIGINFO
при регистрации обработчика сигналов с помощью
sigaction
. Когда член
si_code
структуры
siginfo_t
равен
SI_QUEUE
, то
siginfo_t
представляет член
si_value
, который содержит значение
value
, переданное
sigqueue
.
Ниже приведен пример отправки элемента данных с сигналом. Он устанавливает в очередь три сигнала
SIGRTMIN
с разными элементами данных. Он демонстрирует, что сигналы доставляются в том же порядке, что были отправлены, как мы и ожидаем при работе с сигналами реального времени [73] . Более сложный пример, использующий сигналы для отслеживания изменений в каталогах, можно найти в главе 14.
73
Дополнительные примеры обработки сигналов вы можете найти в программах для аренды файлов (глава 13), управления терминалом (глава 16) и работы с интервальными таймерами (глава 18).
1: /* sigval.с */
2:
3: #include <sys/signal.h>
4: #include <stdlib.h>
5: #include <stdio.h>
6: #include <string.h>
7: #include <unistd.h>
8:
9: /* Захватить сигнал и зарегистрировать факт его обработки */
Отправить сигналы handler и сохранять все сигналы заблокированными,
22: чтобы handler был сконфигурирован для перехвата с исключением
23: состязаний при манипулировании глобальными переменными */
24: act.sa_sigaction = handler;
25: act.sa_mask = mask;
26: act.sa_flags = SA_SIGINFO;
27:
28: sigaction(SIGRTMIN, &act, NULL);
29:
30: /* Блокировать SIGRTMIN, чтобы можно было увидеть очередь и упорядочение*/
31: sigemptyset(&mask);
32: sigaddset(&mask, SIGRTMIN);
33:
34: sigprocmask(SIG_BLOCK, &mask, &oldMask);
35:
36: /* Сгенерировать сигналы */
37: val.sival_int = 1;
38: sigqueue(me, SIGRTMIN, val);
39: val.sival_int++;
40: sigqueue(me, SIGRTMIN, val);
41: val.sival_int++;
42: sigqueue(me, SIGRTMIN, val);
43:
44: /* Разрешить доставку сигналов */
45: sigprocmask(SIG_SETMASK, &oldMask, NULL);
46:
47: return 0;
48: }
Глава 13
Расширенная обработка файлов
В Linux файлы применяются при решении большого количества задач, среди которых, например, хранение долговременных данных, организация сетей с помощью сокетов и доступ к устройствам посредством файлов устройств. Разнообразие приложений, работающих с файлами, привело к созданию множества специальных способов управления файлами. В главе 11 рассматривались наиболее распространенные действия с файлами; в настоящей же главе исследуются специализированные файловые операции. В частности, мы рассмотрим следующие вопросы: использование одновременно нескольких файлов, отображение файлов на системную память, блокировка файлов, чтение и запись вразброс.
13.1. Мультиплексирование входных и выходных данных
Многим клиент-серверным приложениям необходимо считывать входные данные или записывать выходные данные с помощью одновременно нескольких файловых дескрипторов. Например, современные Web-браузеры открывают одновременно несколько сетевых подключений, чтобы уменьшить время загрузки Web-страницы. Это позволяет им загружать множество изображений, имеющихся на большинстве Web-страниц, быстрее, чем с помощью последовательных подключений. Кроме канала межпроцессных взаимодействий (IPC), используемого графическими браузерами для связи с X-сервером, на котором они отображаются, браузеры работают с множеством файловых дескрипторов.