Вход/Регистрация
Linux программирование в примерах
вернуться

Роббинс Арнольд

Шрифт:

Первый набор функций, который мы исследовали, манипулирует значениями

sigset_t
:
sigfillset
,
sigemptyset
,
sigaddset
,
sigdelset
и
sigismember
.

Следующий набор работает с маской сигналов процесса:

sigprocmask
устанавливает и получает маску сигналов процесса,
sigpending
получает набор ожидающих сигналов, a
sigsuspend
помещает процесс в состояние сна, временно заменяя маску сигналов процесса одним из своих параметров.

Функция POSIX API

sigaction
(весьма) запутана из-за необходимости обеспечить:

• обратную совместимость:

SA_RESETHAND
и
SA_RESTART
в поле
sa_flags
;

• выбор, блокировать также полученный сигнал или нет:

SA_NODEFER
для sa
_flags
;

• возможность иметь два различных вида обработчиков сигналов: с одним или с тремя аргументами;

• выбор поведения для управления

SIGCHLD
:
SA_NOCLDSTOP
и
SA_NOCLDWAIT
для
sa_flags
.

Функция

siginterrupt
является удобной для разрешения или запрещения повторного запуска системных вызовов для данного сигнала.

Наконец, для посылки сигналов не только текущему, но также и другим процессам могут использоваться

kill
и
killpg
(конечно, с проверкой прав доступа).

10.7. Сигналы для межпроцессного взаимодействия

«ЭТО УЖАСНАЯ МЫСЛЬ! СИГНАЛЫ НЕ ПРЕДНАЗНАЧЕНЫ ДЛЯ ЭТОГО! Просто скажите НЕТ».

– Джефф Колье (Geoff Collyer) -

Одним из главных механизмов межпроцессного взаимодействия (IPC) являются каналы, которые описаны в разделе 9.3 «Базовая межпроцессная коммуникация каналы и FIFO». Сигналы также можно использовать для очень простого IPC [111] . Это довольно грубо; получатель может лишь сказать, что поступил определенный сигнал. Хотя функция

sigaction
позволяет получателю узнать PID и владельца процесса, пославшего сигнал, эти сведения обычно не очень помогают.

ЗАМЕЧАНИЕ. Как указывает цитата в начале, использование сигналов для IPC почти всегда является плохой мыслью. Мы рекомендуем по возможности избегать этого. Но нашей целью является научить вас, как использовать возможности Linux/Unix, включая их отрицательные моменты, оставляя за вами принятие информированного решения, что именно использовать.

111

Наша благодарность Ульриху Дрепперу (Ulrich Drepper) за помощь в разъяснении, связанных с этим проблем — Примеч. автора.

Сигналы в качестве IPC для многих программ могут быть иногда единственным выбором. В частности, каналы не являются альтернативой, если две взаимодействующие программы не запущены общим родителем, а файлы FIFO могут не быть вариантом, если одна из взаимодействующих программ работает лишь со стандартными вводом и выводом. (Примером обычного использования сигналов являются определенные системные программы демонов, таких, как

xinetd
, которые принимают несколько сигналов, уведомляющих, что нужно повторно прочесть файл настроек, осуществить проверку непротиворечивости и т.д. См. xinetd(8) в системе GNU/Linux и inetd(8) в системе Unix.)

Типичная высокоуровневая структура основанного на сигналах приложения выглядит таким образом:

for(;;){

 /* Ожидание сигнала */

 /* Обработка сигнала */

}

Оригинальным интерфейсом V7 для ожидания сигнала является

pause
:

#include <unistd.h> /* POSIX */

int pause(void);

pause
приостанавливает процесс; она возвращается лишь после того, как сигнал будет доставлен и его обработчик вернется из вызова. По определению,
pause
полезна лишь с перехваченными сигналами — игнорируемые сигналы при их появлении игнорируются, а сигналы с действием по умолчанию, завершающим процесс (с созданием файла образа или без него), продолжают действовать так же.

Проблема в только что описанной высокоуровневой структуре приложения кроется в части «Обработка сигнала». Когда этот код запускается, вы не захотите обрабатывать другой сигнал; вы хотите завершить обработку текущего сигнала до перехода к следующему. Одним из возможных решений является структурирование обработчика сигнала таким образом, что он устанавливает флаг и проверяет его в главном цикле:

volatile sig_atomic_t signal_waiting = 0; /* true, если не обрабатываются сигналы */

void handler(int sig) {

 signal_waiting = 1;

 /* Установка других данных, указывающих вид сигнала */

В основном коде флаг проверяется:

for (;;) {

 if (!signal_waiting) { /* Если возник другой сигнал, */

pause; /* этот код пропускается */

signal_waiting = 1;

 }

 /* Определение поступившего сигнала */

  • Читать дальше
  • 1
  • ...
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: