Из Википедии, бесплатной энциклопедии
  (Перенаправлено из Signal (вычисления) )
Перейти к навигации Перейти к поиску

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

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

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

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

История [ править ]

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

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

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

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

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

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

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

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

Обработка сигналов [ править ]

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

Риски [ править ]

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

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

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

Обработчики сигналов должны быть написаны таким образом, чтобы не приводить к каким-либо нежелательным побочным эффектам, например, к изменению ошибки, изменению маски сигнала, изменению расположения сигнала и другим изменениям атрибутов глобального процесса . Использование нереентерабельных функций, например, malloc или printf , внутри обработчиков сигналов также небезопасно. В частности, спецификация POSIX и справочная страница Linux signal (7) требуют, чтобы все системные функции, прямо или косвенно вызываемые из сигнальной функции, были безопасными для асинхронных сигналов . [5] [6] сигнал безопасности (7)На странице руководства приведен список таких безопасных системных функций async-signal (практически системные вызовы ), в противном случае это неопределенное поведение . [7] Предлагается просто установить некоторую volatile sig_atomic_tпеременную в обработчике сигнала и протестировать ее где-нибудь еще. [8]

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

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

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

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

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

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

Сигналы POSIX [ править ]

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

SIGABRT и SIGIOT
Сигналы SIGABRT и SIGIOT отправляются процессу, чтобы сообщить ему об отмене , то есть о завершении. Сигнал обычно инициируется самим процессом, когда он вызывает abort()функцию стандартной библиотеки C , но он может быть отправлен процессу извне, как любой другой сигнал.
SIGALRM , SIGVTALRM и SIGPROF
Сигналы SIGALRM, SIGVTALRM и SIGPROF отправляются процессу, когда истекает срок, указанный в вызове предыдущей функции установки сигнала тревоги (такой как setitimer). SIGALRM отправляется по истечении реального или часового времени. SIGVTALRM отправляется по истечении процессорного времени, используемого процессом. SIGPROF отправляется, когда время ЦП, используемое процессом и системой от имени процесса, истекает.
SIGBUS
Сигнал SIGBUS отправляется процессу, когда он вызывает ошибку шины . Условия, которые приводят к отправке сигнала, - это, например, неправильное выравнивание доступа к памяти или несуществующий физический адрес.
SIGCHLD
Сигнал SIGCHLD отправляется процессу, когда дочерний процесс завершается , прерывается или возобновляется после прерывания. Одним из распространенных способов использования сигнала является указание операционной системе очистить ресурсы, используемые дочерним процессом после его завершения, без явного вызова waitсистемного вызова.
SIGCONT
Сигнал SIGCONT предписывает операционной системе продолжить (перезапустить) процесс, ранее приостановленный сигналом SIGSTOP или SIGTSTP. Одно из важных применений этого сигнала - управление заданиями в оболочке Unix .
SIGFPE
Сигнал SIGFPE отправляется процессу, когда исключительное (но не обязательно ошибочное) условие было обнаружено в оборудовании для арифметических операций с плавающей запятой или целых чисел. Сюда может входить деление на ноль , потеря значимости или переполнение с плавающей запятой, целочисленное переполнение, недопустимая операция или неточное вычисление. Поведение может отличаться в зависимости от оборудования.
SIGHUP
Сигнал SIGHUP отправляется процессу, когда его управляющий терминал закрыт. Первоначально он был разработан для уведомления о процессе обрыва последовательной линии ( зависания ). В современных системах этот сигнал обычно означает, что управляющий псевдо или виртуальный терминал был закрыт. [9] Многие демоны (у которых нет управляющего терминала) интерпретируют получение этого сигнала как запрос на перезагрузку файлов конфигурации и очистку / повторное открытие файлов журнала вместо выхода. [10] nohup - это команда, заставляющая команду игнорировать сигнал.
СИГИЛЛ
Сигнал SIGILL отправляется процессу, когда он пытается выполнить недопустимую , некорректную, неизвестную или привилегированную инструкцию .
SIGINT
Сигнал SIGINT отправляется процессу его управляющим терминалом, когда пользователь желает прервать процесс. Обычно это запускается нажатием Ctrl+C , но в некоторых системах можно использовать символ « удалить » или « разрыв ». [11]
СИГКИЛЛ
Сигнал SIGKILL отправляется процессу, чтобы вызвать его немедленное завершение ( kill ). В отличие от SIGTERM и SIGINT, этот сигнал нельзя перехватить или проигнорировать, и принимающий процесс не может выполнить какую-либо очистку после получения этого сигнала. Применяются следующие исключения:
  • Зомби-процессы нельзя убить, так как они уже мертвы и ждут, пока их родительские процессы не пожнут их.
  • Процессы, находящиеся в заблокированном состоянии, не умрут, пока снова не проснутся.
  • Процесс init особенный: он не получает сигналов, которые не хочет обрабатывать, и поэтому может игнорировать SIGKILL. [12] Исключением из этого правила является то, что в Linux выполняется трассировка init . [13] [14]
  • Допускающим прерывания спит процесс не может прекратить (и освободить ресурсы) даже при отправке SIGKILL. Это один из немногих случаев, когда может потребоваться перезагрузка системы UNIX для решения временной проблемы программного обеспечения.
SIGKILL используется в качестве последнего средства при завершении процессов в большинстве процедур завершения работы системы, если он не завершается добровольно в ответ на SIGTERM. Чтобы ускорить процедуру выключения компьютера, Mac OS X 10.6, также известная как Snow Leopard , будет отправлять сигнал SIGKILL приложениям, которые пометили себя как «чистые», что приводит к сокращению времени выключения без каких-либо побочных эффектов. [15] Команда killall -9имеет похожий, хотя и опасный эффект, когда выполняется, например, в Linux; он не позволяет программам сохранять несохраненные данные. У него есть другие варианты, и без них используется более безопасный сигнал SIGTERM.
SIGPIPE
Сигнал SIGPIPE отправляется процессу, когда он пытается записать в канал без подключения процесса к другому концу.
SIGPOLL
Сигнал SIGPOLL отправляется, когда событие происходит в явно наблюдаемом файловом дескрипторе. [16] Его использование эффективно приводит к выполнению запросов асинхронного ввода-вывода, поскольку ядро опрашивает дескриптор вместо вызывающего. Это альтернатива активному опросу .
SIGRTMIN в SIGRTMAX
Сигналы от SIGRTMIN к SIGRTMAX предназначены для использования в определенных пользователем целях. Это сигналы в реальном времени .
SIGQUIT
Сигнал SIGQUIT посылается в процесс его управляющий терминалом , когда пользователь запрашивает , что процесс выхода и выполнить дамп .
SIGSEGV
SIGSEGV посылается сигнал процессу , когда он делает недопустимую ссылку виртуальной памяти, или сегментацию ошибки , то есть , когда он выполняет SEG мыслительности v iolation . [17]
SIGSTOP
Сигнал SIGSTOP предписывает операционной системе остановить процесс для последующего возобновления.
SIGSYS
Сигнал SIGSYS отправляется процессу, когда он передает неверный аргумент системному вызову . На практике этот вид сигналов встречается редко, поскольку приложения полагаются на библиотеки (например, libc ) для их вызова. SIGSYS может быть получен приложениями, нарушающими правила безопасности Linux Seccomp, настроенные для их ограничения. SIGSYS также можно использовать для имитации внешних системных вызовов, например, для эмуляции системных вызовов Windows в Linux. [18]
SIGTERM
Сигнал SIGTERM отправляется процессу для запроса его завершения . В отличие от сигнала SIGKILL, он может быть перехвачен и интерпретирован или проигнорирован процессом. Это позволяет процессу выполнять корректное завершение, высвобождая ресурсы и сохраняя состояние, если это необходимо. SIGINT почти идентичен SIGTERM.
SIGTSTP
SIGTSTP сигнал посылается к процессу с помощью контролирующего терминала , чтобы запросить его остановки ( т erminal й о р ). Обычно он запускается нажатием кнопки Ctrl+Z . В отличие от SIGSTOP, процесс может зарегистрировать обработчик сигнала или игнорировать сигнал.
SIGTTIN и SIGTTOU
В SIGTTIN и SIGTTOU сигналы передаются к процессу , когда он пытается прочитать в или записи из соответственно от TTY в то время как в фоновом режиме . Обычно эти сигналы получают только процессы, находящиеся под управлением заданий ; демоны не имеют управляющих терминалов и, следовательно, никогда не должны получать эти сигналы.
SIGTRAP
Сигнал SIGTRAP отправляется процессу, когда возникает исключение (или ловушка ): условие, о котором отладчик запросил информировать - например, когда выполняется определенная функция или когда конкретная переменная меняет значение.
СИГУРГ
Сигнал SIGURG отправляется процессу, когда сокет имеет срочные или внеполосные данные, доступные для чтения.
SIGUSR1 и SIGUSR2
Сигналы SIGUSR1 и SIGUSR2 отправляются процессу для обозначения условий, определенных пользователем .
SIGXCPU
Сигнал SIGXCPU отправляется процессу, когда он израсходовал CPU в течение времени, превышающего определенное заранее заданное пользователем значение. [19] Прибытие сигнала SIGXCPU дает принимающему процессу возможность быстро сохранить любые промежуточные результаты и корректно завершить работу до того, как операционная система завершит его с помощью сигнала SIGKILL.
SIGXFSZ
Сигнал SIGXFSZ отправляется процессу, когда он увеличивает размер файла , превышающего максимально допустимый размер .
SIGWINCH
Сигнал SIGWINCH посылается процессу , когда терминал управления изменяет свой размер (а выигрыш Дау ч АНЖ). [20]

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

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

Portable number:
For most signals the corresponding signal number is implementation-defined. This column lists the numbers specified in the POSIX standard.[21]
Actions explained:
Terminate – Abnormal termination of the process. The process is terminated with all the consequences of _exit() except that the status made available to wait() and waitpid() indicates abnormal termination by the specified signal.
Terminate (core dump) – Abnormal termination of the process. Additionally, implementation-defined abnormal termination actions, such as creation of a core file, may occur.
Ignore – Ignore the signal.
Stop – Stop (not terminate) the process.
Continue – Continue the process, if it is stopped; otherwise, ignore the signal.

Miscellaneous signals[edit]

The following signals are not specified in the POSIX specification. They are, however, sometimes used on various systems.

SIGEMT
The SIGEMT signal is sent to a process when an emulator trap occurs.
SIGINFO
The SIGINFO signal is sent to a process when a status (info) request is received from the controlling terminal.
SIGPWR
The SIGPWR signal is sent to a process when the system experiences a power failure.
SIGLOST
The SIGLOST signal is sent to a process when a file lock is lost.
SIGSTKFLT
The SIGSTKFLT signal is sent to a process when the coprocessor experiences a stack fault (i.e. popping when the stack is empty or pushing when it is full).[22] It is defined by, but not used on Linux, where a x87 coprocessor stack fault will generate SIGFPE instead.[23]
SIGUNUSED
The SIGUNUSED signal is sent to a process when a system call with an unused system call number is made. It is synonymous with SIGSYS on most architectures.[22]
SIGCLD
The SIGCLD signal is synonymous with SIGCHLD.[22]

See also[edit]

  • C signal handling

References[edit]

  1. ^ McIlroy, M. D. (1987). A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986 (PDF) (Technical report). CSTR. Bell Labs. 139.
  2. ^ "Termination Signals". The GNU C Library).
  3. ^ "Job Control Signals". The GNU C Library.
  4. ^ "Miscellaneous Signals". The GNU C Library.
  5. ^ "The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition: System Interfaces Chapter 2". pubs.opengroup.org. Retrieved 20 December 2020.
  6. ^ "signal(7) - Linux manual page". man7.org. Retrieved 20 December 2020.
  7. ^ "signal-safety(7) - Linux manual page". man7.org. Retrieved 20 December 2020.
  8. ^ "The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition: <signal.h>". pubs.opengroup.org. Retrieved 20 December 2020.
  9. ^ Michael Kerrisk (25 July 2009). "signal(7)". Linux Programmer's Manual (version 3.22). The Linux Kernel Archives. Retrieved 23 September 2009.
  10. ^ "perlipc(1)". Perl Programmers Reference Guide, version 5.18. perldoc.perl.org - Official documentation for the Perl programming language. Retrieved 21 September 2013.
  11. ^ "Proper handling of SIGINT and SIGQUIT". Retrieved 6 October 2012.
  12. ^ https://manpages.ubuntu.com/manpages/zesty/man2/kill.2.html section NOTES
  13. ^ "SIGKILL init process (PID 1)". Stack Overflow.
  14. ^ "Can root kill init process?". Unix & Linux Stack Exchange.
  15. ^ "Mac Dev Center: What's New in Mac OS X: Mac OS X v10.6". 28 August 2009. Retrieved 18 November 2017.
  16. ^ "ioctl - controls a STREAM device". POSIX system call specification. The Open Group. Retrieved 19 June 2015.
  17. ^ "What is a "segmentation violation"?". support.microfocus.com. Retrieved 22 November 2018.
  18. ^ "Syscall User Dispatch – The Linux Kernel documentation". kernel.org. Retrieved 11 February 2021.
  19. ^ "getrlimit, setrlimit - control maximum resource consumption". POSIX system call specification. The Open Group. Retrieved 10 September 2009.
  20. ^ Clausecker, Robert (19 June 2017). "0001151: Introduce new signal SIGWINCH and functions tcsetsize(), tcgetsize() to get/set terminal window size". Austin Group Defect Tracker. Austin Group. Retrieved 12 October 2017. Accepted As Marked
  21. ^ "IEEE Std 1003.1-2017 - kill". IEEE, Open Group. The correspondence between integer values and the sig value used is shown in the following list. The effects of specifying any signal_number other than those listed below are undefined.
  22. ^ a b c "signal(7) — Linux manual pages". manpages.courier-mta.org. Retrieved 22 November 2018.
  23. ^ "Linux 3.0 x86_64: When is SIGSTKFLT raised?". Stack Overflow.
  • Stevens, W. Richard (1992). Advanced Programming in the UNIX® Environment. Reading, Massachusetts: Addison Wesley. ISBN 0-201-56317-7.
  • "The Open Group Base Specifications Issue 7, 2013 Edition". The Open Group. Retrieved 19 June 2015.

External links[edit]

  • Unix Signals Table, Ali Alanjawi, University of Pittsburgh
  • Man7.org Signal Man Page
  • Introduction To Unix Signals Programming Introduction To Unix Signals Programming at the Wayback Machine (archived 26 September 2013)
  • Another Introduction to Unix Signals Programming (blog post, 2009)
  • UNIX and Reliable POSIX Signals by Baris Simsek
  • Signal Handlers by Henning Brauer