Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Интернет » Linux программирование в примерах - Роббинс Арнольд

Linux программирование в примерах - Роббинс Арнольд

Читать онлайн Linux программирование в примерах - Роббинс Арнольд

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 141 142 143 144 145 146 147 148 149 ... 253
Перейти на страницу:

2095

2096  raise(sig); /* Повторно послать сигнал */

2097 }

Вот код в main(), который помещает обработчик на свое место:

2214 #ifdef SA_NOCLDSTOP /* На системе POSIX... */

2215 {

2216  unsigned i;

2217  sigemptyset(&caught_signals);

2218  for (i = 0; i < nsigs; i++) /* - Блокировать все сигналы */

2219   sigaddset(&caught_signals, sigs[i]);

2220  newact.sa_handler = sighandler; /* - Функция обработки сигнала */

2221  newact.sa_mask = caught_signals; /* - Установить для обработчика маску сигналов процесса */

2222  newact.sa_flags =0; /* - Особых флагов нет */

2223 }

2224 #endif

2225

2226 {

2227  unsigned i;

2228  for (i = 0; i < nsigs; i++) /* Для всех сигналов... */

2229  {

2230   int sig = sigs[i];

2231 #ifdef SA_NOCLDSTOP

2232   sigaction(sig, NULL, &oldact); /* - Получить старый обработчик */

2233   if (oldact.sa_handler != SIG_IGN) /* - Если этот сигнал не игнорируется */

2234    sigaction(sig, &newact, NULL); /* - Установить наш обработчик */

2235 #else

2236   if (signal(sig, SIG_IGN) != SIG_IGN)

2237    signal(sig, sighandler); /* - Та же логика со старым API */

2238 #endif

2239  }

2240 }

Мы заметили, что строки 2216–2219 и 2221 могут быть замещены одним вызовом: sigfillset(&newact.sa_mask);

Мы не знаем, почему код написан именно таким способом.

Интерес представляют также строки 2233–2234 и 2236–2237, которые показывают правильный способ проверки того, игнорируется ли сигнал, и для установки обработчика лишь в том случае, если сигнал не игнорируется.

ЗАМЕЧАНИЕ. Функции 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 указывает на проблему.

1 ... 141 142 143 144 145 146 147 148 149 ... 253
Перейти на страницу:
Тут вы можете бесплатно читать книгу Linux программирование в примерах - Роббинс Арнольд.
Комментарии