Роббинс Арнольд
Шрифт:
ЗАМЕЧАНИЕ. Функции API
sigaction
и signal
не должны использоваться вместе для одного и того же сигнала. Хотя POSIX идет на большие длинноты, чтобы сначала сделать возможным использование signal
, получить struct sigaction
, представляющую диспозицию signal
, и восстановить ее, все равно это плохая мысль. Код будет гораздо проще читать, писать и понимать, если вы используете одну функцию или другую взаимоисключающим образам 10.6.5. Извлечение ожидающих сигналов:
sigpending
Описанный ранее системный вызов
sigpending
позволяет получить набор ожидающих сигналов, т.е тех сигналов, которые появились, но еще не доставлены из-за блокировки: #include <signal.h> /* POSIX */
int sigpending(sigset_t *set);
Помимо разблокировки ожидающих сигналов, чтобы они могли быть доставлены, вы можете решить их игнорировать. Установка действия сигнала
SIG_IGN
вызывает сбрасывание сигнала (даже если он был заблокирован). Сходным образом для тех сигналов, действием по умолчанию для которых является их игнорирование, установка действия в SIG_DFL
также вызывает сбрасывание таких ожидающих сигналов. 10.6.6. Создание возможности для прерывания функций:
siginterrupt
Чтобы сделать определенную функцию прерываемой или повторно запускаемой в зависимости от значения второго аргумента, в качестве удобного средства может использоваться функция
siginterrupt
. Объявление следующее: #include <signal.h> /* XSI */
int siginterrupt(int sig, int flag);
В соответствии со стандартом POSIX поведение
siginterrupt
эквивалентно следующему коду: int siginterrupt(int sig, int flag) {
int ret;
struct sigaction act;
(void)sigaction(sig, NULL, &act); /* Получить старые установки */
if (flag) /* Если flag равен true... */
act.sa_flags &= ~SA_RESTART; /* Запретить повторный запуск */
else /* В противном случае... */
act.sa_flags |= SA_RESTART; /* Разрешить повторный запуск */
ret = sigaction(sig, &act, NULL);
/* Поместить новые установки на место */
return ret; /* Вернуть результат */
}
В случае успеха возвращаемое значение равно 0 и -1 при ошибке.
10.6.7. Передача сигналов:
kill
и killpg
Традиционная функция Unix для передачи сигналов называется
kill
. Имя несколько неправильное; все, что она делает — отправляет сигнал. (Результатом этого часто является завершение получателя сигнала, но это не обязательно верно. Однако, теперь слишком поздно менять имя.) Функция killpg
посылает сигнал определенной группе процессов. Объявления следующие: #include <sys/types.h> /* POSIX */
#include <signal.h>
int kill(pid_t pid, int sig);
int killpg(int pgrp, int sig); /* XSI */
Аргумент
sig
является либо именем сигнала, либо 0. В последнем случае сигнал не посылается, но ядро все равно осуществляет проверку ошибок. В частности, это правильный способ проверки существования данного процесса или группы, а также проверки того, что у вас есть разрешение на передачу сигналов процессу или группе процессов kill
возвращает 0 в случае успеха и -1 при ошибке; errno
указывает на проблему. Правила для значения
pid
несколько запутаны: pid > 0
pid
является номером процесса, и сигнал посылается этому процессу pid = 0
Сигнал посылается каждому процессу в группе посылающего процесса. pid = -1
Сигнал посылается каждому процессу в системе, за исключением специальных системных процессов. Применяется проверка прав доступа. На системах GNU/Linux исключается лишь процесс init
(PID 1), но у других систем могут быть другие специальные процессы. pid < -1
Сигнал посылается группе процессов, представленной абсолютным значением pid
. Таким образом, вы можете отправить сигнал всей группе процессов, дублируя возможности killpg
. Эта неортогональность обеспечивает историческую совместимость. Значение
pid
для kill
сходно со значением для waitpid
(см. раздел 9.1.6.1 «Использование функций POSIX: wait
и waitpid
»). Стандартная функция С
raise
в сущности эквивалентна