Сигнал (IPC) - Signal (IPC)

Сигналы являются ограниченной формой межпроцессного взаимодействия (IPC), обычно используется в Unix, Unix-подобный, и другие POSIX -совместимые операционные системы. Сигнал - это асинхронный уведомление отправлено процесс или конкретному нить в рамках того же процесса, чтобы уведомить его о произошедшем событии. Сигналы зародились в 1970-х годах. Bell Labs Unix и недавно были указаны в POSIX стандарт.

Когда сигнал отправлен, операционная система прерывает нормальный процесс целевого процесса. поток исполнения доставить сигнал. Исполнение может быть прервано во время любого неатомарная инструкция. Если процесс ранее зарегистрировал обработчик сигналов, эта процедура выполняется. В противном случае выполняется обработчик сигнала по умолчанию.

Встроенные программы могут найти сигналы полезными для межпроцессного взаимодействия, так как объем вычислений и памяти для сигналов невелик.

Сигналы похожи на прерывает с той разницей, что прерывания обрабатываются процессором и обрабатываются ядро а сигналы передаются ядром (возможно, через системные вызовы) и обрабатываются процессами. Ядро может передать прерывание как сигнал процессу, который его вызвал (типичные примеры: SIGSEGV, SIGBUS, СИГИЛЛ и SIGFPE ).

История

Версия 1 Unix был отдельный системные вызовы для перехвата прерываний, завершений и машинных ловушек. Версия 4 объединил все ловушки в один звонок, сигнал, и каждая пронумерованная ловушка получила символическое имя в Версия 7. убийство появился в Версия 2, И в Версия 5 мог посылать произвольные сигналы.[1] План 9 от Bell Labs заменил сигналы на Примечания, которые позволяют отправлять короткие произвольные строки.[нужна цитата ]

Отправка сигналов

В убийство (2) Системный вызов отправляет указанный сигнал указанному процессу, если позволяют разрешения. Точно так же убить (1) Команда позволяет пользователю отправлять сигналы процессам. В поднять (3) Библиотечная функция отправляет указанный сигнал текущему процессу.

Исключения Такие как деление на ноль или нарушение сегментации будет генерировать сигналы (здесь SIGFPE "исключение с плавающей запятой" и SIGSEGV "нарушение сегментации" соответственно, которые по умолчанию вызывают дамп ядра и выход из программы).

Ядро может генерировать сигналы для уведомления процессов о событиях. Например, SIGPIPE будет генерироваться, когда процесс записывает в канал, который был закрыт читателем; по умолчанию это приводит к завершению процесса, что удобно при построении оболочки трубопроводов.

Ввод определенных комбинаций клавиш на управляющий терминал запущенного процесса заставляет систему отправлять ему определенные сигналы:[2]

  • Ctrl-C (в старых версиях Unix, DEL) отправляет сигнал INT ("прерывание", SIGINT ); по умолчанию это приводит к завершению процесса.
  • Ctrl-Z отправляет сигнал TSTP («конечная остановка», SIGTSTP ); по умолчанию это заставляет процесс приостанавливать выполнение.[3]
  • Ctrl- посылает сигнал QUIT (SIGQUIT ); по умолчанию это вызывает завершение процесса и выгрузку ядра.
  • Ctrl-T (поддерживается не во всех UNIX) отправляет сигнал INFO (СИГИНФО ); по умолчанию, и если это поддерживается командой, это заставляет операционную систему отображать информацию о запущенной команде.[4]

Эти комбинации клавиш по умолчанию в современных операционных системах можно изменить с помощью stty команда.

Обработка сигналов

Обработчики сигналов могут быть установлены с сигнал (2) или же sigaction (2) системный вызов. Если обработчик сигнала не установлен для определенного сигнала, используется обработчик по умолчанию. В противном случае сигнал перехватывается и вызывается обработчик сигнала. Процесс также может указать два поведения по умолчанию без создания обработчика: игнорировать сигнал (SIG_IGN) и использовать обработчик сигнала по умолчанию (SIG_DFL). Есть два сигнала, которые нельзя перехватить и обработать: СИГКИЛЛ и SIGSTOP.

Риски

Обработка сигналов уязвима для условия гонки. Поскольку сигналы являются асинхронными, другой сигнал (даже того же типа) может быть доставлен процессу во время выполнения процедуры обработки сигналов.

В sigprocmask (2) call можно использовать для блокировки и разблокировки доставки сигналов. Заблокированные сигналы не доставляются в процесс, пока не будут разблокированы. Сигналы, которые нельзя игнорировать (SIGKILL и SIGSTOP), нельзя заблокировать.

Сигналы могут вызывать прерывание текущего системного вызова, оставляя приложение для управления непрозрачный перезапуск.

Обработчики сигналов должны быть написаны таким образом, чтобы не приводить к нежелательным побочным эффектам, например errno изменение, изменение маски сигнала, изменение расположения сигнала и другие глобальные процесс изменения атрибутов. Использование не-повторно въезжающий функции, например, маллок или же printf, внутренние обработчики сигналов также небезопасны. В частности, POSIX спецификация и справочная страница Linux сигнал (7) требует, чтобы все функции системы работали напрямую или косвенно вызываемые из сигнальной функции безопасный асинхронный сигнал. сигнальная безопасность (7) дает список таких функций системы безопасности async-signal (практически системные вызовы ), иначе это неопределенное поведение. это предложенный просто установить некоторые летучий sig_atomic_t переменная в обработчике сигнала и протестировать ее в другом месте.

Обработчики сигналов могут вместо этого помещать сигнал в очередь и сразу вернусь. Затем основной поток будет продолжать "непрерывно" до тех пор, пока сигналы не будут взяты из очереди, например, в цикл событий. «Непрерывность» здесь означает, что операции, которые блокировать может вернуться преждевременно и должен быть возобновлен, как уже упоминалось выше. Сигналы должны обрабатываться из очереди в основном потоке, а не через рабочие пулы, поскольку это вновь вводит проблему асинхронности. Однако управление очередью невозможно безопасным способом с асинхронным сигналом только sig_atomic_t, поскольку только одиночные операции чтения и записи в такие переменные гарантированно будут атомарными, а не приращениями или (выборкой и) -декрементами, как это требуется для очереди. Таким образом, эффективно, только один сигнал на обработчик может быть безопасно поставлен в очередь с sig_atomic_t пока он не будет обработан.

Связь с аппаратными исключениями

А процесс выполнение может привести к созданию аппаратного исключение, например, если процесс пытается разделить на ноль или вызывает ошибка страницы.

В Unix-подобный операционных систем, это событие автоматически меняет процессор контекст начать выполнение ядро обработчик исключений. В случае некоторых исключений, таких как ошибка страницы, ядро ​​имеет достаточно информации для полной обработки самого события и возобновления выполнения процесса.

Однако другие исключения ядро ​​не может обрабатывать разумно, и вместо этого оно должно отложить операцию обработки исключения процессу, вызвавшему сбой. Эта отсрочка достигается с помощью механизма сигналов, при котором ядро ​​отправляет процессу сигнал, соответствующий текущему исключению. Например, если процесс попытался разделить целое число на ноль на x86 ЦПУ, а ошибка разделения будет сгенерировано исключение, и ядро ​​отправит SIGFPE сигнал к процессу.

Точно так же, если процесс попытался получить доступ к адресу памяти за пределами своего виртуальное адресное пространство, ядро ​​уведомит процесс об этом нарушении через SIGSEGV сигнал. Точное соответствие между именами сигналов и исключениями, очевидно, зависит от ЦП, поскольку типы исключений различаются в зависимости от архитектуры.

Сигналы POSIX

Список ниже документирует сигналы, указанные в Единая спецификация Unix. Все сигналы определены как макроконстанты в <signal.h> заголовочный файл. Имя макроконстанты состоит из символа «SIG». префикс за которым следует мнемоническое имя сигнала.

SIGABRT и SIGIOT
Сигналы SIGABRT и SIGIOT отправляются процессу, чтобы сообщить ему прервать, т.е. прекратить. Сигнал обычно инициируется самим процессом, когда он вызывает прерывание () функция Стандартная библиотека C, но он может быть отправлен процессу извне, как и любой другой сигнал.
SIGALRM, SIGVTALRM и SIGPROF
Сигналы SIGALRM, SIGVTALRM и SIGPROF отправляются процессу, когда ограничение по времени, указанное в вызове предыдущего тревога функция настройки (например, setitimer) истекает. SIGALRM отправляется по истечении реального или часового времени. SIGVTALRM отправляется по истечении процессорного времени, используемого процессом. SIGPROF отправляется, когда время ЦП, используемое процессом и системой от имени процесса, истекает.
SIGBUS
В SIGBUS сигнал отправляется процессу, когда он вызывает ошибка шины. Условия, которые приводят к отправке сигнала, - это, например, неправильное выравнивание доступа к памяти или несуществующий физический адрес.
SIGCHLD
В SIGCHLD сигнал отправляется процессу, когда дочерний процесс прекращается, прерывается или возобновляется после прерывания. Одним из распространенных способов использования сигнала является указание операционной системе очистить ресурсы, используемые дочерним процессом после его завершения, без явного вызова ждать системный вызов.
SIGCONT
В SIGCONT сигнал указывает операционной системе Продолжить (перезапустить) процесс, ранее приостановленный сигналом SIGSTOP или SIGTSTP. Одно из важных применений этого сигнала - контроль работы в Оболочка Unix.
SIGFPE
Сигнал SIGFPE отправляется процессу, когда он выполняет ошибочную арифметическую операцию, например деление на ноль. Это может включать целочисленное деление на ноль и целочисленное переполнение в результате деления (из C доступны только INT_MIN / -1, INT64_MIN / -1 и% -1).[5][6]
SIGHUP
В SIGHUP сигнал отправляется процессу, когда его управляющий терминал закрыт. Первоначально он был разработан для уведомления о процессе последовательная линия капля (а вешать трубку). В современных системах этот сигнал обычно означает, что управляющий псевдо или виртуальный терминал был закрыт.[7] Много демоны будет перезагружать свои файлы конфигурации и повторно открывать свои файлы журналов вместо выхода при получении этого сигнала.[8] нету это команда, заставляющая команду игнорировать сигнал.
СИГИЛЛ
Сигнал SIGILL отправляется процессу, когда он пытается выполнить незаконный, неправильный, неизвестный или привилегированный инструкция.
SIGINT
Сигнал SIGINT отправляется процессу его управляющим терминалом, когда пользователь желает прерывать процесс. Обычно это инициируется нажатием Ctrl+C, но в некоторых системах "Удалить "персонаж или"перемена "ключ может быть использован.[9]
СИГКИЛЛ
Сигнал SIGKILL отправляется процессу, чтобы немедленно завершить его (убийство). В отличие от SIGTERM и SIGINT, этот сигнал нельзя перехватить или проигнорировать, и принимающий процесс не может выполнить какую-либо очистку после получения этого сигнала. Применяются следующие исключения:
  • Зомби-процессы не могут быть убиты, так как они уже мертвы и ждут, пока их родительские процессы пожнут их.
  • Процессы, находящиеся в заблокированном состоянии, не умрут, пока снова не проснутся.
  • В в этом процесс особенный: он не получает сигналов, которые не хочет обрабатывать, и поэтому может игнорировать SIGKILL.[10] Исключением из этого правила является то, что init прослежен в Linux.[11][12]
  • An непрерывно спит процесс не может завершиться (и освободить свои ресурсы) даже при отправке SIGKILL. Это один из немногих случаев, когда может потребоваться перезагрузка системы UNIX для решения временной проблемы программного обеспечения.
SIGKILL используется как последнее средство при завершении процессов в большинстве систем. неисправность процедуры, если он не выходит добровольно в ответ на SIGTERM. Для ускорения процедуры выключения компьютера Mac OS X 10.6, также известная как Снежный барс, отправит сигнал SIGKILL приложениям, которые пометили себя как «чистые», что приведет к более быстрому завершению работы без каких-либо негативных последствий.[13] Команда killall -9 имеет аналогичный, хотя и опасный эффект, когда выполняется, например в Linux; он не позволяет программам сохранять несохраненные данные. У него есть другие варианты, и без них используется более безопасный сигнал SIGTERM.
SIGPIPE
Сигнал SIGPIPE отправляется процессу, когда он пытается записать в трубка без процесса, подключенного к другому концу.
SIGPOLL
Сигнал SIGPOLL отправляется, когда событие происходит в явно наблюдаемом файловом дескрипторе.[14] Его эффективное использование приводит к созданию асинхронный ввод / вывод запросы, так как ядро ​​будет опрос дескриптор вместо вызывающего. Это альтернатива активному опрос.
SIGRTMIN к SIGRTMAX
Сигналы от SIGRTMIN к SIGRTMAX предназначены для использования в определенных пользователем целях. Они есть в реальном времени сигналы.
SIGQUIT
Сигнал SIGQUIT отправляется процессу его управляющим терминалом, когда пользователь запрашивает, чтобы процесс покидать и выполнить дамп ядра.
SIGSEGV
В SIGSEGV сигнал отправляется процессу, когда он делает недопустимую ссылку на виртуальную память, или ошибка сегментации, т.е. когда он выполняет сегмышление vожесточение.[15]
SIGSTOP
В SIGSTOP сигнал указывает операционной системе остановка процесс для последующего возобновления.
SIGSYS
Сигнал SIGSYS отправляется процессу, когда он передает неверный аргумент в системный вызов. На практике такой сигнал редко встречается, поскольку приложения полагаются на библиотеки (например, libc ), чтобы позвонить за них. SIGSYS может быть получен приложениями, нарушающими Linux Seccomp правила безопасности настроены для их ограничения.
SIGTERM
Сигнал SIGTERM отправляется процессу, чтобы запросить его прекращение. В отличие от сигнала SIGKILL, он может быть пойман и интерпретирован или проигнорирован процессом. Это позволяет процессу выполнять корректное завершение, высвобождая ресурсы и сохраняя состояние, если необходимо. SIGINT почти идентичен SIGTERM.
SIGTSTP
В SIGTSTP сигнал отправляется процессу, контролируя Терминал запросить это остановка (тгорностай улоп). Обычно он инициируется нажатием кнопки Ctrl+Z. В отличие от SIGSTOP, процесс может зарегистрировать обработчик сигнала или игнорировать сигнал.
SIGTTIN и SIGTTOU
В SIGTTIN и SIGTTOU сигналы отправляются процессу, когда он пытается прочитать в или напишите из соответственно от tty в то время как в фон. Обычно эти сигналы получают только процессы под контроль работы; демоны не имеют управляющих клемм и, следовательно, никогда не должны получать эти сигналы.
SIGTRAP
Сигнал SIGTRAP отправляется процессу, когда исключение (или ловушка) возникает: условие, что отладчик запросил информацию - например, когда конкретный функция выполняется, или когда конкретный Переменная меняет значение.
СИГУРГ
В СИГУРГ сигнал отправляется процессу, когда разъем имеет срочный или же внеполосные данные доступно для чтения.
SIGUSR1 и SIGUSR2
Сигналы SIGUSR1 и SIGUSR2 отправляются процессу, чтобы указать определяемые пользователем условия.
SIGXCPU
Сигнал SIGXCPU отправляется процессу, когда он израсходовал ЦПУ на время, которое превышает определенное заранее заданное значение, устанавливаемое пользователем.[16] Прибытие сигнала SIGXCPU дает принимающему процессу возможность быстро сохранить любые промежуточные результаты и корректно завершить работу до того, как операционная система завершит его с помощью сигнала SIGKILL.
SIGXFSZ
Сигнал SIGXFSZ отправляется процессу, когда он увеличивает файл который превышает максимально допустимый размер.
SIGWINCH
Сигнал SIGWINCH отправляется процессу, когда его управляющий терминал изменяет свой размер ( победитьдоу chангл.).[17]

Действие по умолчанию

Процесс может определять как обрабатывать входящие сигналы POSIX. Если процесс не определяет поведение для сигнала, то обработчик по умолчанию для этого сигнала используется. В таблице ниже перечислены некоторые действия по умолчанию для POSIX-совместимых систем UNIX, например FreeBSD, OpenBSD и Linux.

СигналПортативный
номер
Действие по умолчаниюОписание
SIGABRT6Завершить (дамп ядра)Сигнал прерывания процесса
SIGALRM14ПрекратитьБудильник
SIGBUSНет данныхЗавершить (дамп ядра)Доступ к неопределенной части объекта памяти
SIGCHLDНет данныхИгнорироватьДочерний процесс завершен, остановлен или продолжен
SIGCONTНет данныхПродолжатьПродолжить выполнение, если остановлено
SIGFPE8Завершить (дамп ядра)Ошибочная арифметическая операция
SIGHUP1ПрекратитьВешать трубку
СИГИЛЛ4Завершить (дамп ядра)Незаконная инструкция
SIGINT2ПрекратитьСигнал прерывания клеммы
СИГКИЛЛ9ПрекратитьУбить (нельзя поймать или проигнорировать)
SIGPIPE13ПрекратитьПишите на трубе, и некому читать
SIGPOLLНет данныхПрекратитьОпрашиваемое событие
SIGPROFНет данныхПрекратитьТаймер профилирования истек
SIGQUIT3Завершить (дамп ядра)Сигнал выхода из терминала
SIGSEGV11Завершить (дамп ядра)Неверная ссылка на память
SIGSTOPНет данныхОстанавливатьсяОстановить выполнение (нельзя поймать или проигнорировать)
SIGSYSНет данныхЗавершить (дамп ядра)Плохой системный вызов
SIGTERM15ПрекратитьСигнал завершения
SIGTRAP5Завершить (дамп ядра)Ловушка трассировки / точки останова
SIGTSTPНет данныхОстанавливатьсяСигнал остановки терминала
SIGTTINНет данныхОстанавливатьсяФоновый процесс пытается прочитать
SIGTTOUНет данныхОстанавливатьсяФоновый процесс пытается записать
SIGUSR1Нет данныхПрекратитьОпределяемый пользователем сигнал 1
SIGUSR2Нет данныхПрекратитьОпределяемый пользователем сигнал 2
СИГУРГНет данныхИгнорироватьВнеполосные данные доступен в розетке
SIGVTALRMНет данныхПрекратитьСрок действия виртуального таймера истек
SIGXCPUНет данныхЗавершить (дамп ядра)Превышен лимит времени ЦП
SIGXFSZНет данныхЗавершить (дамп ядра)Превышен предел размера файла
SIGWINCHНет данныхИгнорироватьРазмер окна терминала изменен
Портативный номер:
Для большинства сигналов соответствующий номер сигнала определяется реализацией. В этом столбце перечислены числа, указанные в стандарте POSIX.[18]
Объяснение действий:
Прекратить - Аномальное прекращение процесса. Процесс завершается со всеми последствиями _exit (), за исключением того, что статус, доступный для wait () и waitpid (), указывает на ненормальное завершение заданным сигналом.
Завершить (дамп ядра) - Аномальное прекращение процесса. Кроме того, могут возникать определенные реализацией аномальные действия завершения, такие как создание основного файла.
Игнорировать - Игнорируйте сигнал.
Останавливаться - Остановить (не прекратить) процесс.
Продолжать - Продолжить процесс, если он остановлен; в противном случае игнорируйте сигнал.

Разные сигналы

Следующие сигналы не указаны в POSIX Технические характеристики. Однако иногда они используются в различных системах.

SIGEMT
Сигнал SIGEMT отправляется процессу, когда эмулятор ловушка происходит.
СИГИНФО
Сигнал SIGINFO отправляется процессу, когда статус (Информация) запрос получен от управляющего терминала.
SIGPWR
Сигнал SIGPWR отправляется процессу, когда в системе сбой питания.
СИГЛОСТ
Сигнал SIGLOST отправляется процессу, когда блокировка файла потерял.
SIGSTKFLT
Сигнал SIGSTKFLT отправляется процессу, когда сопроцессор испытывает улack жault (т.е. появляется, когда стек пуст, или нажимает, когда он заполнен).[19] Он определен, но не используется в Linux, где x87 ошибка стека сопроцессора вместо этого сгенерирует SIGFPE.[20]
SIGUNUSED
Сигнал SIGUNUSED отправляется процессу, когда системный вызов с неиспользованный номер системного вызова. Это синоним SIGSYS на большинстве архитектур.[19]
SIGCLD
Сигнал SIGCLD является синонимом SIGCHLD.[19]

Смотрите также

Рекомендации

  1. ^ Макилрой, М.Д. (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). CSTR. Bell Labs. 139.
  2. ^ "Сигналы завершения". Библиотека GNU C).
  3. ^ «Сигналы управления заданиями». Библиотека GNU C.
  4. ^ «Разные сигналы». Библиотека GNU C.
  5. ^ https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/arm/lib1funcs.S#L1493
  6. ^ https://web.archive.org/web/20161110002617/http://en.chys.info/2009/12/floating-point-exception/
  7. ^ Майкл Керриск (25 июля 2009 г.). "сигнал (7)". Руководство программиста Linux (версия 3.22). Архивы ядра Linux. Получено 23 сентября 2009.
  8. ^ "perlipc (1)". Справочное руководство программистов Perl, версия 5.18. perldoc.perl.org - Официальная документация по языку программирования Perl. Получено 21 сентября 2013.
  9. ^ «Правильное обращение с SIGINT и SIGQUIT». Получено 6 октября 2012.
  10. ^ https://manpages.ubuntu.com/manpages/zesty/man2/kill.2.html Примечания к разделу
  11. ^ "Процесс инициализации SIGKILL (PID 1)". Переполнение стека.
  12. ^ "Может ли root убить процесс инициализации?". Обмен стеков Unix и Linux.
  13. ^ «Центр разработки для Mac: что нового в Mac OS X: Mac OS X v10.6». 28 августа 2009 г.. Получено 18 ноября 2017.
  14. ^ «ioctl - управляет устройством STREAM». POSIX спецификация системного вызова. Открытая группа. Получено 19 июн 2015.
  15. ^ "Что такое" нарушение сегментации "?". support.microfocus.com. Получено 22 ноября 2018.
  16. ^ "getrlimit, setrlimit - контролировать максимальное потребление ресурсов". POSIX спецификация системного вызова. Открытая группа. Получено 10 сентября 2009.
  17. ^ Клаузекер, Роберт (19 июня 2017 г.). «0001151: Представьте новый сигнал SIGWINCH и функции tcsetsize (), tcgetsize () для получения / установки размера окна терминала». Система отслеживания дефектов Austin Group. Остин Групп. Получено 12 октября 2017. Принято как отмеченное
  18. ^ «IEEE Std 1003.1-2017 - убить». IEEE, открытая группа. Соответствие целочисленных значений и сиг Используемое значение показано в следующем списке. Эффекты указания любых signal_number кроме перечисленных ниже не определены.
  19. ^ а б c "signal (7) - справочные страницы Linux". manpages.courier-mta.org. Получено 22 ноября 2018.
  20. ^ «Linux 3.0 x86_64: когда поднимается SIGSTKFLT?». Переполнение стека.

внешняя ссылка