- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Linux программирование в примерах - Арнольд Роббинс
Шрифт:
Интервал:
Закладка:
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 указывает на проблему.
Правила для значения 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() в сущности эквивалентна
int raise(int sig) {
return kill(getpid(), sig);
}
Комитет по стандартизации С выбрал имя raise(), поскольку С должен работать также в окружениях, не относящихся к Unix, a kill() была сочтена специфичной для Unix функцией. Представилась также возможность дать этой функции более описательное имя.
killpg() посылает сигнал группе процессов. Пока значение pgrp превышает 1, эта функция эквивалентна 'kill(-pgrp, sig)'. Справочная страница GNU/Linux killpg(2) утверждает, что если pgrp равно 0, сигнал посылается группе отправляющего процесса (Это то же самое, что и kill().)
Как вы могли представить, нельзя послать сигнал произвольному процессу (если вы не являетесь суперпользователем, root). Для обычных пользователей действительный или эффективный UID отправляющего процесса должен соответствовать действительному или сохраненному set-user-ID получающего процесса. (Различные UID описаны в разделе 11.1.1 «Действительные и эффективные ID».)
Однако SIGCONT является особым случаем: пока получающий процесс является членом того же сеанса, что и отправляющий, сигнал пройдет. (Сеансы были кратко описаны в разделе 9.2.1 «Обзор управления заданиями».) Это особое правило позволяет управляющей заданиями оболочке продолжать остановленные процессы-потомки, даже если этот остановленный процесс имеет другой ID пользователя.
10.6.8. Наша история до настоящего времени, эпизод II
System V Release 3 API был предназначен для исправления различных проблем, представленных первоначальным API сигналов V7. В частности, важной дополнительной концепцией является понятие о блокировке сигналов.
Однако, этот API оказался недостаточным, поскольку он работал лишь с одним сигналом за раз, оставляя множество широко открытых окон, через которые могли поступать нежелательные сигналы. POSIX API, работая атомарно с множеством сигналов (маской сигналов процесса, программно представленной типом sigset_t), решает эту проблему, закрывая окна.
Первый набор функций, который мы исследовали, манипулирует значениями 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 и владельца процесса, пославшего сигнал, эти сведения обычно не очень помогают.

