Что такое sig линукс

Что такое sig линукс

Сигналы являются программными прерываниями, которые посылаются процессу, когда случается некоторое событие. Сигналы могут возникать синхронно с ошибкой в приложении, например SIGFPE (ошибка вычислений с плавающей запятой) и SIGSEGV (ошибка адресации), но большинство сигналов является асинхронными. Сигналы могут посылаться процессу, если система обнаруживает программное событие, например, когда пользователь дает команду прервать или остановить выполнение, или получен сигнал на завершение от другого процесса. Сигналы могут прийти непосредственно от ядра ОС, когда возникает сбой аппаратных средств ЭВМ. Система определяет набор сигналов, которые могут быть отправлены процессу. В Linux применяется около 30 различных сигналов. При этом каждый сигнал имеет целочисленное значение и приводит к строго определенным действиям.

Механизм передачи сигналов состоит из следующих частей:

  • установление и обозначение сигналов в форме целочисленных значений;
  • маркер в строке таблицы процессов для прибывших сигналов;
  • таблица с адресами функций, которые определяют реакцию на прибывающие сигналы.

Отдельные сигналы подразделяются на три класса:

  • системные сигналы (ошибка аппаратуры, системная ошибка и т.д.);
  • сигналы от устройств;
  • сигналы, определенные пользователем.

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

Известно три варианта реакции на сигналы:

  • вызов собственной функции обработки;
  • игнорирование сигнала (не работает для SIGKILL );
  • использование предварительно установленной функции обработки по умолчанию.

Чтобы реагировать на разные сигналы, необходимо знать концепции их обработки. Процесс должен организовать так называемый обработчик сигнала в случае его прихода. Для этого используется функция signal ():

void(*signal(int signr, void(*sighandler)(int)))(int); Такой прототип очень сложен для понимания. Следует упростить его, определив тип для функции обработки:

typedef void signalfunction(int); После этого прототип функции примет вид: signalfunction *signal(int signr,

signalfunction *sighandler); signr устанавливает номер сигнала, для которого устанавливается обработчик. В заголовочном файле определены следующие сигналы (табл. 1).

Номер Значение Реакция программы по умолчанию
SIGABRT Ненормальное завершение (abort()) Завершение
SIGALRM Окончание кванта времени Завершение
SIGBUS Аппаратная ошибка Завершение
SIGCHLD Изменение состояния потомка Игнорирование
SIGCONT Продолжение прерванной программы Продолжение / игнорирование
SIGEMT Аппаратная ошибка Завершение
SIGFPE Ошибка вычислений с плавающей запятой Завершение
SIGILL Неразрешенная аппаратная команда Завершение
SIGINT Прерывание с терминала Завершение
SIGIO Асинхронный ввод/вывод Игнорирование
SIGKILL Завершение программы Завершение
SIGPIPE Запись в канал без чтения Завершение
SIGPWR Сбой питания Игнорирование
SIGQUIT Прерывание с клавиатуры Завершение
SIGSEGV Ошибка адресации Завершение
SIGSTOP Остановка процесса Остановка
SIGTTIN Попытка чтения из фонового процесса Остановка
SIGTTOU Попытка записи в фоновый процесс Остановка
SIGUSR1 Пользовательский сигнал Завершение
SIGUSR2 Пользовательский сигнал Завершение
SIGXCPU Превышение лимита времени CPU Завершение
SIGXFSZ Превышение пространства памяти (4GB) Завершение
SIGURG Срочное событие Игнорирование
SIGWINCH Изменение размера окна Игнорирование

Переменная sighandler определяет функцию обработки сигнала. В заголовочном файле определены две константы SIG_DFL и SIG_IGN . SIG_DFL означает выполнение действий по умолчанию — в большинстве случаев — окончание процесса. Например, определение signal(SIGINT, SIG_DFL); приведет к тому, что при нажатии на комбинацию клавиш CTRL+C во время выполнения сработает реакция по умолчанию на сигнал SIGINT и программа завершится. С другой стороны, можно определить
signal(SIGINT, SIG_IGN);

Если теперь нажать на комбинацию клавиш CTRL+C , ничего не произойдет, так как сигнал SIGINT игнорируется. Третьим способом является перехват сигнала SIGINT и передача управления на адрес собственной функции, которая должна выполнять действия, если была нажата комбинация клавиш CTRL+C , например
signal(SIGINT, function);

Пример использования обработчика сигнала приведен ниже: #include

void sigfunc(int sig) <

printf(«\nХотите завершить программу (y/n) : «);

Источник

Что такое sig линукс

В таблицах далее есть столбец «Действие», в котором указан обработчик по умолчанию для каждого сигнала:

Term Действие по умолчанию — завершение процесса. Ign Действие по умолчанию — игнорирование сигнала. Core Действие по умолчанию — завершение процесса и вывод дампа в файл (смотрите core(5)). Stop Действие по умолчанию — остановка процесса. Cont Действие по умолчанию — продолжение работы процесса, если он в данный момент остановлен.

Процесс может изменить обработчик сигнала с помощью sigaction(2) или signal(2) (менее переносим; дополнительную информацию смотрите в signal(2)). Используя данные системные вызовы процесс может выбрать одно из следующих действий при получении сигнала: выполнить действие по умолчанию, игнорировать сигнал, поймать сигнал обработчиком сигнала — функцией, задаваемой программистом, которая автоматически вызывается при получении сигнала (по умолчанию обработчик сигнала использует обычный стек процесса. Возможно сделать так, чтобы обработчик сигнала использовал альтернативный стек; как это делается и когда это может быть полезно смотрите в sigaltstack(2)).

Реакция на сигналы является атрибутом процесса: в многонитиевом приложении реакция на определённый сигнал одинакова для всех нитей.

Потомок, созданный с помощью fork(2), наследует реакцию на сигналы от своего родителя. При execve(2) реакция на сигналы устанавливается в значение по умолчанию; реакция на игнорируемые сигналы не изменяется.

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

Ожидание сигнала для обработки

Синхронный приём сигнала

Сигнальная маска и ожидающие сигналы

В каждой нити процесса имеется независимая сигнальная маска, определяющая набор сигналов, которые нить, в данный момент, блокирует. Нить может управлять сигнальной маской с помощью pthread_sigmask(3). В обычном однонитиевом приложении для работы с сигнальной маской можно использовать вызов sigprocmask(2).

Потомок, создаваемый с помощью fork(2), наследует копию родительской маски сигналов; маска сигналов сохраняется при вызове execve(2).

Сигнал может быть сгенерирован (а значит и стать ожидающим) как для всего процесса (например, при отправке с помощью kill(2)) так и для отдельной нити (например, некоторые сигналы, такие как SIGSEGV и SIGFPE, сгенерированные в следствии выполнения определённой инструкции на машинном языке в самой нити, или сигналы, направленные определённой нити с помощью pthread_kill(3)). Направленный процессу сигнал может быть доставлен в любую из нитей, у которых сигнал не заблокирован. Если имеется несколько таких нитей, то ядро выбирает произвольную нить, которой и доставит сигнал.

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

Потомок, созданный с помощью fork(2), первоначально имеет пустой набор ожидающих сигналов; набор ожидающих сигналов сохраняется при вызове execve(2).

Стандартные сигналы

Сначала рассмотрим сигналы, описанные в стандарте POSIX.1-1990.

Сигнал Номер Действие Комментарий
терминалом, либо завершение управляющего
терминалом процесса
SIGINT 2 Term Прерывание с клавиатуры
SIGQUIT 3 Core Выход с клавиатуры
SIGILL 4 Core Несуществующая инструкция
SIGABRT 6 Core Сигнал аварии (abort), посланный
abort(3)
SIGFPE 8 Core Ошибка операций с плавающей запятой
SIGKILL 9 Term Kill-сигнал
SIGSEGV 11 Core Некорректная ссылка в память
SIGPIPE 13 Term Оборванный канал: запись в канал,
из которого не читают
SIGALRM 14 Term Сигнал таймера, посланный alarm(2)
SIGTERM 15 Term Сигнал завершения
SIGUSR1 30,10,16 Term Первый сигнал, определяемый
пользователем
SIGUSR2 31,12,17 Term Второй сигнал, определяемый
пользователем
SIGCHLD 20,17,18 Ign Потомок остановлен или прекратил
выполнение
SIGCONT 19,18,25 Cont Продолжить выполнение, если остановлен
SIGSTOP 17,19,23 Stop Остановить выполнение процесса
SIGTSTP 18,20,24 Stop Останов введён с терминала
SIGTTIN 21,21,26 Stop Ввод с терминала у фонового процесса
SIGTTOU 22,22,27 Stop Вывод на терминал у фонового процесса

Сигналы SIGKILL и SIGSTOP нельзя поймать, заблокировать или проигнорировать.

Далее приведены сигналы, не входящие в POSIX.1-1990, но описанные в SUSv2 и POSIX.1-2001.

Сигнал Номер Действие Комментарий
доступа)
SIGPOLL Term Событие опроса (Sys V).
Синоним SIGIO
SIGPROF 27,27,29 Term Закончилось время профилирующего
таймера
SIGSYS 12,31,12 Core Недопустимый аргумент для процедуры
(SVr4)
SIGTRAP 5 Core Ловушка трассировки/отладки
SIGURG 16,23,21 Ign Приоритетное состояние у сокета
(4.2BSD)
SIGVTALRM 26,26,28 Term Виртуальный таймер (4.2BSD)
SIGXCPU 24,24,30 Core Превышено время работы на ЦП (4.2BSD)
SIGXFSZ 25,25,31 Core Превышен размер файла (4.2BSD)

В Linux до версии 2.2 включительно поведением по умолчанию для сигналов SIGSYS, SIGXCPU, SIGXFSZ и SIGBUS (на всех архитектурах кроме SPARC и MIPS) было завершение процесса без создания дампа (в некоторых системах UNIX действием по умолчанию для SIGXCPU и SIGXFSZ является завершение процесса без создания дампа). Linux версии 2.4 соответствует требованиям POSIX.1-2001 для этих сигналов и завершает процесс с созданием дампа.

Некоторые другие сигналы.

Сигнал Номер Действие Комментарий
SIGEMT 7,-,7 Term
SIGSTKFLT -,16,- Term Ошибка стека на сопроцессоре
(не используется)
SIGIO 23,29,22 Term Теперь возможен ввод/вывод (4.2BSD)
SIGCLD -,-,18 Ign Синоним SIGCHLD
SIGPWR 29,30,19 Term Отказ системы питания (System V)
SIGINFO 29,-,- Синоним SIGPWR
SIGLOST -,-,- Term Утрачена блокировка файла (не используется)
SIGWINCH 28,28,20 Ign Сигнал изменения размера окна
(4.3BSD, Sun)
SIGUNUSED -,31,- Core Синоним SIGSYS

Сигнал с номером 29 на alpha соответствует SIGINFO / SIGPWR, а на sparc соответствует SIGLOST.

Сигнал SIGEMT не определён в POSIX.1-2001, но, тем не менее, появляется почти во всех системах UNIX, где действием по умолчанию для него является завершение процесса с созданием дампа.

Сигнал SIGPWR (не определён в POSIX.1-2001) по умолчанию, обычно, игнорируется (в других системах UNIX).

Для сигнала SIGIO (не определён в POSIX.1-2001) в других системах UNIX действием по умолчанию является игнорирование.

Если определён сигнал SIGUNUSED, то он является синонимом SIGSYS для большинства архитектур.

Сигналы реального времени

Ядро Linux поддерживает 33 таких сигнала, начиная с номера 32 до номера 64. Однако внутри реализации нитей POSIX в glibc используется два (для NPTL) или три (для LinuxThreads) сигнала реального времени (смотрите pthreads(7)), а значение SIGRTMIN корректируется должным образом (до 34 или 35). Так как диапазон доступных сигналов реального времени различается в зависимости от реализации нитей в glibc (и это может происходить во время выполнения при смене ядра и glibc), и, более того, диапазон сигналов реального времени различен в разных системах UNIX, то программы никогда не должны задавать сигналы реального времени по номерам, а вместо этого всегда должны записывать их в виде SIGRTMIN+n и выполнять проверку (во время выполнения), что SIGRTMIN+n не превышает SIGRTMAX.

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

Действием по умолчанию для необработанных сигналов реального времени является завершение процесса (terminate).

Сигналы реального времени отличаются от обычных в следующем:

1. В очередь можно добавлять несколько экземпляров одного сигнала реального времени. В случае со стандартными сигналами, если доставляется несколько экземпляров сигнала, в то время как этот тип сигнала в данный момент заблокирован, то только один экземпляр будет добавлен в очередь. 2. Если сигнал отправляется с помощью sigqueue(3), то с сигналом может быть отправлено некоторое значение (целочисленное, либо указатель). Если принимающий процесс устанавливает обработчик для сигнала, используя флаг SA_SIGINFO и вызов sigaction(2), то он может получить это значение через поле si_value структуры siginfo_t, переданной обработчику в виде второго аргумента. Кроме этого, поля si_pid и si_uid данной структуры можно использовать для получения идентификатора процесса и реального идентификатора пользователя, отправившего сигнал. 3. Сигналы реального времени доставляются точно в порядке поступления. Несколько сигналов одного типа доставляются в порядке, определяемых их отправлением. Если процессу отправлено несколько разных сигналов реального времени, то порядок их доставки начинается с сигнала с наименьшим номером (то есть сигналы с наименьшим номером имеют наивысший приоритет). Порядок же для стандартных сигналов в такой ситуации не определён.

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

В соответствии с POSIX, реализация должна позволять ставить в очередь процесса как минимум _POSIX_SIGQUEUE_MAX (32) сигнала. Однако в Linux это делается по-другому. В ядрах до версии 2.6.7 включительно, Linux накладывает общесистемный лимит на количество сигналов режима реального времени в очереди для всех процессов. Этот лимит может быть получен и изменён (если есть права) через файл /proc/sys/kernel/rtsig-max. Текущее количество сигналов режима реального времени в очереди можно получить из файла /proc/sys/kernel/rtsig-nr. В Linux 2.6.8 данные интерфейсы /proc были заменены на ограничение ресурса RLIMIT_SIGPENDING, которое устанавливает ограничение на очередь сигналов на каждого пользователя отдельно; дополнительную информацию можно найти в setrlimit(2).

Для дополнительных сигналов или сигналов реального времени требуется расширение структуры набора сигналов (sigset_t) с 32 до 64 бит. В связи с этим, различные системные вызовы заменены на новые системные вызов, поддерживающие набор сигналов большего размера. Вот соответствие старых и новых системных вызовов:

Linux 2.0 и старее Linux 2.2 и новее
sigaction(2) rt_sigaction(2)
sigpending(2) rt_sigpending(2)
sigprocmask(2) rt_sigprocmask(2)
sigreturn(2) rt_sigreturn(2)
sigsuspend(2) rt_sigsuspend(2)
sigtimedwait(2) rt_sigtimedwait(2)

Безопасные асинхронные функции при работе с сигналами

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

Согласно POSIX.1-2004 (также называемом POSIX.1-2001 Technical Corrigendum 2) от реализации требуется гарантировать, что следующие функции можно безопасно вызывать из обработчика сигнала:

В POSIX.1-2008 из списка выше удалены функции fpathconf(), pathconf() и sysconf() и добавлены следующие:

В POSIX.1-2008 Technical Corrigendum 1 (2013) добавлены следующие функции:

Прерывание системных вызовов и библиотечных функций обработчиками сигналов

Выбираемое поведение зависит от интерфейса и от того, был ли обработчик сигнала установлен с флагом SA_RESTART (смотрите sigaction(2)). Но в различных системах UNIX есть другие различия; далее описаны подробности для Linux.

Если заблокированный вызов к одному из следующих интерфейсов прерван обработчиком сигнала, то вызов будет автоматически перезапущен после завершения обработчика сигнала, если задействован флаг SA_RESTART; иначе вызов завершается с ошибкой EINTR:

* Вызовы read(2), readv(2), write(2), writev(2) и ioctl(2) для «медленных» устройств. «Медленным» называют устройство, которое может навсегда заблокировать ввод-вывод, например, терминал, канал или сокет. Если вызов ввода-вывода для медленного устройства уже передал немного данных на момент прерывания обработчиком сигнала, то вызов вернёт состояние успешного выполнения (обычно, количество переданных байт). Заметим, что диск (локальный) не подходит под определение медленного устройства; операции ввода-вывода с дисками не прерываются сигналами. * Вызов open(2), если он может выполнить блокировку (например, при открытии FIFO; смотрите fifo(7)). * Вызовы wait(2), wait3(2), wait4(2), waitid(2) и waitpid(2). * Интерфейсы сокетов: accept(2), connect(2), recv(2), recvfrom(2), recvmmsg(2), recvmsg(2), send(2), sendto(2) и sendmsg(2), если для сокета не указано время ожидания (смотрите далее). * Интерфейсы файловой блокировки: flock(2) и операции F_SETLKW и F_OFD_SETLKW у fcntl(2). * Интерфейсы очереди сообщений POSIX: mq_receive(3), mq_timedreceive(3), mq_send(3) и mq_timedsend(3). * Вызов futex(2) с FUTEX_WAIT (начиная с Linux 2.6.22; до этой версии вызов завершался с ошибкой EINTR). * getrandom(2). * pthread_mutex_lock(3), pthread_cond_wait(3) связанный с этим программный интерфейс. * futex(2) FUTEX_WAIT_BITSET. * Интерфейсы семафоров POSIX: sem_wait(3) и sem_timedwait(3) (начиная с Linux 2.6.22; до этой версии вызовы завершались с ошибкой EINTR).

Следующие интерфейсы никогда не перезапускаются после прерывания обработчиком сигнала независимо от наличия SA_RESTART; они всегда завершаются с ошибкой EINTR, если прерываются обработчиком сигнала:

Функция sleep(3) также никогда не перезапускается, если прервана обработчиком сигнала, но сообщает об успешном выполнении: возвращает количество оставшиеся для сна секунд.

Прерывание системных вызовов и библиотечных функций сигналами останова

Интерфейсы Linux, к которым это относится:

* «Входные» интерфейсы сокетов, если установлен таймаут (SO_RCVTIMEO) на сокете с помощью setsockopt(2): accept(2), recv(2), recvfrom(2), recvmmsg(2) (также с аргументом timeout, не равным NULL) и recvmsg(2). * «Выходные» интерфейсы сокетов, если установлен таймаут (SO_RCVTIMEO) на сокете с помощью setsockopt(2): connect(2), send(2), sendto(2) и sendmsg(2), если установлен таймаут отправления (SO_SNDTIMEO). * epoll_wait(2), epoll_pwait(2). * semop(2), semtimedop(2). * sigtimedwait(2), sigwaitinfo(2). * read(2) из файлового дескриптора inotify(7). * Linux версии 2.6.21 и более ранних: futex(2) FUTEX_WAIT, sem_timedwait(3), sem_wait(3). * Linux версии 2.6.8 и более ранних: msgrcv(2), msgsnd(2). * Linux версии 2.4 и более ранних: nanosleep(2).

Источник

Читайте также:  Супер обои для windows
Оцените статью