Linux программирование в примерах
Правила для значения
несколько запутаны:pidpid > 0является номером процесса, и сигнал посылается этому процессуpidСигнал посылается каждому процессу в группе посылающего процесса.pid = 0Сигнал посылается каждому процессу в системе, за исключением специальных системных процессов. Применяется проверка прав доступа. На системах GNU/Linux исключается лишь процессpid = -1(PID 1), но у других систем могут быть другие специальные процессы.initСигнал посылается группе процессов, представленной абсолютным значениемpid < -1. Таким образом, вы можете отправить сигнал всей группе процессов, дублируя возможностиpid. Эта неортогональность обеспечивает историческую совместимость.killpg()Значение
дляpidсходно со значением дляkill()(см. раздел 9.1.6.1 «Использование функций POSIX:waitpid()иwait()»).waitpid()Стандартная функция С
в сущности эквивалентнаraise()int raise(int sig) {return kill(getpid(), sig);}Комитет по стандартизации С выбрал имя
, поскольку С должен работать также в окружениях, не относящихся к Unix, araise()была сочтена специфичной для Unix функцией. Представилась также возможность дать этой функции более описательное имя.kill()посылает сигнал группе процессов. Пока значениеkillpg()превышает 1, эта функция эквивалентна 'pgrp'. Справочная страница GNU/Linux killpg(2) утверждает, что еслиkill(-pgrp, sig)равно 0, сигнал посылается группе отправляющего процесса (Это то же самое, что иpgrp.)kill()Как вы могли представить, нельзя послать сигнал произвольному процессу (если вы не являетесь суперпользователем,
). Для обычных пользователей действительный или эффективный UID отправляющего процесса должен соответствовать действительному или сохраненному set-user-ID получающего процесса. (Различные UID описаны в разделе 11.1.1 «Действительные и эффективные ID».)rootОднако
является особым случаем: пока получающий процесс является членом того же сеанса, что и отправляющий, сигнал пройдет. (Сеансы были кратко описаны в разделе 9.2.1 «Обзор управления заданиями».) Это особое правило позволяет управляющей заданиями оболочке продолжать остановленные процессы-потомки, даже если этот остановленный процесс имеет другой ID пользователя.SIGCONT10.6.8. Наша история до настоящего времени, эпизод II
System V Release 3 API был предназначен для исправления различных проблем, представленных первоначальным API сигналов V7. В частности, важной дополнительной концепцией является понятие о блокировке сигналов.
Однако, этот API оказался недостаточным, поскольку он работал лишь с одним сигналом за раз, оставляя множество широко открытых окон, через которые могли поступать нежелательные сигналы. POSIX API, работая атомарно с множеством сигналов (маской сигналов процесса, программно представленной типом
), решает эту проблему, закрывая окна.sigset_tПервый набор функций, который мы исследовали, манипулирует значениями
:sigset_t,sigfillset(),sigemptyset(),sigaddset()иsigdelset().sigismember()Следующий набор работает с маской сигналов процесса:
устанавливает и получает маску сигналов процесса,sigprocmask()получает набор ожидающих сигналов, asigpending()помещает процесс в состояние сна, временно заменяя маску сигналов процесса одним из своих параметров.sigsuspend()Функция POSIX API
(весьма) запутана из-за необходимости обеспечить:sigaction()• обратную совместимость:
иSA_RESETHANDв полеSA_RESTART;sa_flags• выбор, блокировать также полученный сигнал или нет:
для saSA_NODEFER;_flags• возможность иметь два различных вида обработчиков сигналов: с одним или с тремя аргументами;
• выбор поведения для управления
:SIGCHLDиSA_NOCLDSTOPдляSA_NOCLDWAIT.sa_flagsФункция
является удобной для разрешения или запрещения повторного запуска системных вызовов для данного сигнала.siginterrupt()Наконец, для посылки сигналов не только текущему, но также и другим процессам могут использоваться
иkill()(конечно, с проверкой прав доступа).killpg()10.7. Сигналы для межпроцессного взаимодействия
«ЭТО УЖАСНАЯ МЫСЛЬ! СИГНАЛЫ НЕ ПРЕДНАЗНАЧЕНЫ ДЛЯ ЭТОГО! Просто скажите НЕТ».
Одним из главных механизмов межпроцессного взаимодействия (IPC) являются каналы, которые описаны в разделе 9.3 «Базовая межпроцессная коммуникация каналы и FIFO». Сигналы также можно использовать для очень простого IPC [111]. Это довольно грубо; получатель может лишь сказать, что поступил определенный сигнал. Хотя функция
позволяет получателю узнать PID и владельца процесса, пославшего сигнал, эти сведения обычно не очень помогают.sigaction()ЗАМЕЧАНИЕ. Как указывает цитата в начале, использование сигналов для IPC почти всегда является плохой мыслью. Мы рекомендуем по возможности избегать этого. Но нашей целью является научить вас, как использовать возможности Linux/Unix, включая их отрицательные моменты, оставляя за вами принятие информированного решения, что именно использовать.
Сигналы в качестве IPC для многих программ могут быть иногда единственным выбором. В частности, каналы не являются альтернативой, если две взаимодействующие программы не запущены общим родителем, а файлы FIFO могут не быть вариантом, если одна из взаимодействующих программ работает лишь со стандартными вводом и выводом. (Примером обычного использования сигналов являются определенные системные программы демонов, таких, как
, которые принимают несколько сигналов, уведомляющих, что нужно повторно прочесть файл настроек, осуществить проверку непротиворечивости и т.д. См. xinetd(8) в системе GNU/Linux и inetd(8) в системе Unix.)xinetd