Что вызывает отправку различных сигналов?

28

Иногда меня смущают все сигналы, которые может получать процесс. Насколько я понимаю, у процесса есть обработчик по умолчанию ( расположение сигналов ) для каждого из этих сигналов, но он может предоставить свой собственный обработчик путем вызова sigaction().

Итак, вот мой вопрос: что вызывает отправку каждого из сигналов? Я понимаю, что вы можете вручную отправлять сигналы запущенным процессам через -sпараметр kill, но каковы естественные обстоятельства, при которых эти сигналы отправляются? Например, когда SIGINTбудет отправлено?

Кроме того, есть ли какие-либо ограничения на какие сигналы могут быть обработаны? Можно SIGSEGVли обрабатывать даже сигналы и возвращать управление в приложение?

Натан Осман
источник
Правильный ответ на этот вопрос будет грандиозным, и в основном будет повторять информацию по этому вопросу в статье в Википедии , поэтому я просто укажу на это.
Шон Дж. Гофф
@Shawn: В статье в Википедии есть список сигналов, но нет четкого представления о том, кто какие сигналы посылает.
Жиль "ТАК ... перестать быть злым"

Ответы:

41

В дополнение к вызову процессов 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.

Жиль "ТАК - перестань быть злым"
источник
И SIGHUP, ваш модем повесил трубку. :-)
Кит
1
Еще одна вещь, на которую следует обратить внимание: SIGFPEнесколько неинтуитивно, также сообщается о делении целых чисел на ноль, а иногда и о целочисленном переполнении со знаком.
Эфимент
18

Сначала отвечу на ваш второй вопрос: 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.
Jander
источник
Какой сигнал отправляется при использовании shutdownкоманды?
Натан Осман
Это зависит от сценариев выключения. Обычно SIGTERMотправляется первым, затем идет задержка, затем SIGKILL. В принципе, для жесткого немедленного выключения ядру вообще не нужно отправлять сигнал; это может просто прекратить запуск процесса.
Джандер