Иногда меня смущают все сигналы, которые может получать процесс. Насколько я понимаю, у процесса есть обработчик по умолчанию ( расположение сигналов ) для каждого из этих сигналов, но он может предоставить свой собственный обработчик путем вызова sigaction()
.
Итак, вот мой вопрос: что вызывает отправку каждого из сигналов? Я понимаю, что вы можете вручную отправлять сигналы запущенным процессам через -s
параметр kill
, но каковы естественные обстоятельства, при которых эти сигналы отправляются? Например, когда SIGINT
будет отправлено?
Кроме того, есть ли какие-либо ограничения на какие сигналы могут быть обработаны? Можно SIGSEGV
ли обрабатывать даже сигналы и возвращать управление в приложение?
Ответы:
В дополнение к вызову процессов
kill(2)
, некоторые сигналы отправляются ядром (или иногда самим процессом) при различных обстоятельствах:SIGINT
(пожалуйста, вернитесь в основной цикл) на Ctrl+ C,SIGQUIT
(пожалуйста, немедленно прекратите) на Ctrl+ \,SIGTSTP
(пожалуйста, приостановите) на Ctrl+ Z. Ключи могут быть изменены с помощьюstty
команды.SIGTTIN
иSIGTTOU
отправляются, когда фоновый процесс пытается прочитать или записать на свой управляющий терминал.SIGWINCH
посылается, чтобы сигнализировать, что размер окна терминала изменился.SIGHUP
посылается сигнал о том , что терминал исчез (исторически , потому что ваш модем имел ч тичная вверх , в настоящее время , как правило , потому что вы закрыли окно эмуляции терминала).SIGBUS
для невыровненного доступа к памяти;SIGSEGV
для доступа к неотображенной странице;SIGILL
за недопустимую инструкцию (плохой код операции);SIGFPE
для инструкции с плавающей точкой с плохими аргументами (напримерsqrt(-1)
).SIGALRM
уведомляет, что таймер, установленный процессом, истек. Таймеры могут быть установлены с помощьюalarm
,setitimer
и другие.SIGCHLD
уведомляет процесс, что один из его детей умер.SIGPIPE
генерируется, когда процесс пытается записать в канал, когда конец чтения закрыт (идея состоит в том, что, если вы запуститеfoo | bar
иbar
выйдете,foo
будет убитSIGPIPE
).SIGPOLL
(также называетсяSIGIO
) уведомляет процесс о том, что произошло событие pollable. POSIX определяет события, подлежащие опросу, зарегистрированные черезI_SETSIG
ioctl
. Многие системы допускают опрашиваемые события для любого дескриптора файла, установленного с помощьюO_ASYNC
fcntl
флага. Связанный сигналSIGURG
, который уведомляет о срочных данных на устройстве (зарегистрированном черезI_SETSIG
ioctl
) или сокет .SIGPWR
отправляется всем процессам, когда ИБП сигнализирует о неизбежности сбоя питания.Эти списки не являются исчерпывающими. Стандартные сигналы определены в
signal.h
.Большинство сигналов может быть поймано и обработано (или проигнорировано) приложением. Единственными двумя переносимыми сигналами, которые не могут быть перехвачены, являются
SIGKILL
(просто умереть) иSTOP
(остановить выполнение).SIGSEGV
( ошибка сегментации ) и ее двоюродный братSIGBUS
( ошибка шины ) могут быть обнаружены, но это плохая идея, если вы действительно не знаете, что делаете. Обычное приложение для их перехвата - это печать трассировки стека или другой отладочной информации. Более продвинутое приложение - реализовать некое управление внутрипроцессной памятью или перехватывать неверные инструкции в механизмах виртуальных машин.Наконец, позвольте мне упомянуть то, что не является сигналом. Когда вы нажимаете Ctrl+ Dв начале строки в программе, которая читает ввод с терминала, это сообщает программе, что конец входного файла достигнут. Это не сигнал: он передается через API ввода / вывода. Как Ctrl+ Cи друзья, ключ может быть настроен с
stty
.источник
SIGFPE
несколько неинтуитивно, также сообщается о делении целых чисел на ноль, а иногда и о целочисленном переполнении со знаком.Сначала отвечу на ваш второй вопрос:
SIGSTOP
иSIGKILL
не может быть пойман приложением, но любой другой сигнал может, дажеSIGSEGV
. Это свойство полезно для отладки - например, при правильной поддержке библиотеки вы можете прослушатьSIGSEGV
и сгенерировать обратную трассировку стека, чтобы показать, где именно произошла ошибка.Официальное слово (в любом случае для Linux) о том, что делает каждый сигнал, можно получить, набрав
man 7 signal
в командной строке Linux. http://linux.die.net/man/7/signal содержит ту же информацию, но таблицы труднее читать.Однако, без некоторого опыта с сигналами, из коротких описаний трудно понять, что они делают на практике, поэтому вот моя интерпретация:
Срабатывает от клавиатуры
SIGINT
происходит , когда вы попалиCTRL+C
.SIGQUIT
запускаетсяCTRL+\
и сбрасывает ядро.SIGTSTP
приостанавливает вашу программу, когда вы нажимаетеCTRL+Z
. В отличие от этогоSIGSTOP
, его можно отловить, что дает программамvi
возможность перевести терминал в безопасное состояние перед тем, как приостановить работу.Терминальные взаимодействия
SIGHUP
(«Зависание») - это то, что происходит, когда вы закрываете свой xterm (или иным образом отключаете терминал) во время работы вашей программы.SIGTTIN
иSIGTTOU
приостановить вашу программу, если она пытается читать или записывать в терминал, пока он работает в фоновом режиме. ЧтобыSIGTTOU
это произошло, я думаю, что программа должна писать/dev/tty
, а не просто стандартный вывод.Вызывается исключением процессора
Это означает, что ваша программа пыталась сделать что-то не так.
SIGILL
означает незаконную или неизвестную инструкцию процессора. Это может произойти, например, если вы попытались получить прямой доступ к портам ввода-вывода процессора.SIGFPE
означает, что произошла аппаратная математическая ошибка; скорее всего программа пыталась делить на ноль.SIGSEGV
означает, что ваша программа пыталась получить доступ к не отображенной области памяти.SIGBUS
означает, что программа неправильно обращалась к памяти каким-либо другим способом; Я не буду вдаваться в подробности для этого резюме.Процесс взаимодействия
SIGPIPE
произойдет, если вы попытаетесь записать в канал после того, как читатель канала закроет их конец. Смman 7 pipe
.SIGCHLD
происходит, когда созданный вами дочерний процесс либо завершается, либо приостанавливается (SIGSTOP
или аналогичным образом).Полезно для самосигнализации
SIGABRT
обычно вызывается программой, вызывающейabort()
функцию, и по умолчанию вызывает дамп ядра. Вроде "кнопка паники".SIGALRM
вызваноalarm()
системным вызовом, который заставит ядро доставитьSIGALRM
программу через указанное количество секунд. Смотритеman 2 alarm
иman 2 sleep
.SIGUSR1
иSIGUSR2
используются, однако программа любит. Они могут быть полезны для сигнализации между процессами.Отправлено администратором
Эти сигналы обычно отправляются из командной строки, с помощью
kill
команды илиfg
илиbg
в случаеSIGCONT
.SIGKILL
иSIGSTOP
являются неблокируемыми сигналами. Первый всегда завершает процесс немедленно; вторая приостанавливает процесс.SIGCONT
возобновляет приостановленный процесс.SIGTERM
это ловимая версияSIGKILL
.источник
shutdown
команды?SIGTERM
отправляется первым, затем идет задержка, затемSIGKILL
. В принципе, для жесткого немедленного выключения ядру вообще не нужно отправлять сигнал; это может просто прекратить запуск процесса.