Чтобы принять union sigval
, процесс, перехватывающий сигнал, должен использовать SA_SIGINFO
при регистрации обработчика сигналов с помощью sigaction()
. Когда член si_code
структуры siginfo_t
равен SI_QUEUE
, то siginfo_t
представляет член si_value
, который содержит значение value
, переданное sigqueue
.
Ниже приведен пример отправки элемента данных с сигналом. Он устанавливает в очередь три сигнала SIGRTMIN
с разными элементами данных. Он демонстрирует, что сигналы доставляются в том же порядке, что были отправлены, как мы и ожидаем при работе с сигналами реального времени[73]. Более сложный пример, использующий сигналы для отслеживания изменений в каталогах, можно найти в главе 14.
1: /* sigval.с */
2:
3: #include
4: #include
5: #include
6: #include
7: #include
8:
9: /* Захватить сигнал и зарегистрировать факт его обработки */
10: void handler(int signo, siginfo_t *si, void *context) {
11: printf("%d\n", si->si_value.sival_int);
12: }
13:
14: int main() {
15: sigset_t mask;
16: sigset_t oldMask;
17: struct sigaction act;
18: int me = getpid();
19: union sigval val;
20:
21: /* Отправить сигналы 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-сервером, на котором они отображаются, браузеры работают с множеством файловых дескрипторов.
Браузеру легче всего обработать эти файлы, считывая и обрабатывая данные из них (системный вызов read()
в сетевом подключении, так же, как и в канале, возвращает доступные в настоящий момент данные и блокирует их только в случае неготовности). Этот подход эффективен, пока все подключения доставляют данные достаточно регулярно.