- Сигналы, группы, сеансы
- Сигнал, маска, обработчик
- Примеры использования сигналов
- Список сигналов
- Posix.1-1990
- Отправка сигнала
- Исторический способ обработки сигнала — signal
- Реакция на сигнал — sigaction
- Параметры для установки обработчика сигнала через sigaction()
- Данные, передаваемые в обработчик сигнала sa_sigaction()
- Блокирование сигналов
- Манипулирование маской
- Проверка наличия заблокированных сигналов
- Очистка заблокированных сигналов
- Управляющий терминал, сеанс, группы
- Управляющий терминал, сеанс, группы
- Группа процессов
- Сеанс
- Фоновая группа сеанса
- Управляющий терминал
- Что такое sig linux
Сигналы, группы, сеансы
Сигналы в Unix указывают ядру, что надо прервать нормальное планирование процесса и завершить/остановить его, или, вместо продолжения выполнения процесса с места остановки, выполнить функцию — обработчик сигнала, и лишь затем продолжить выполнение основного кода.
Сигналы, предназначенные процессу, создаются (отправляются) в нескольких ситуациях: при аппаратных сбоях, при срабатывании особого таймера, при обработке спецсимволов (Ctrl C, Ctrl Z) драйвером управляющего терминала, с помощью системного вызова kill(). В зависимости от причины, отправляются сигналы разных типов. Тип сигнала обозначается целым числом (номером). В Linux сигналы нумеруются от 1 до 64. Сигнал может быть отправлен отдельной нити процесса, процессу в целом или группе процессов.
Для каждого номера сигнала в процессе (нити) предусмотрено некоторое действие (действие по умолчанию, игнорирование или вызов пользовательской функции). Доставка сигнала заключается в выполнении этого действия.
Между отправкой сигнала и его доставкой проходит некоторое непредсказуемое время, поскольку, обычно, сигналы обрабатываются (доставляются) при выходе из системных вызовов или в тот момент, когда планировщик назначает процесс на выполнение. Исключением является доставка сигнала SIGKILL остановленным процессам. Для большинства сигналов можно явно приостановить доставку с помощью установки маски блокирования доставки sigprocmask() , и, в случае необходимости, удалить сигнал без обработки с помощью sigwait() .
Сигналы SIGKILL и SIGSTOP не могут быть заблокированы или проигнорированы и на них нельзя установить свой обработчик.
Действия по умолчанию:
- SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU — остановка процесса
- SIGCONT — запуск остановленного процесса
- SIGCHLD — игнорируется
- SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGSEGV — сохранение дампа памяти и завершение (Linux)
- остальные — завершение процесса
Сигнал, маска, обработчик
В упрощенном виде структуру в ядре, обеспечивающую доставку сигналов процессу, можно представить как таблицу:
Номер | Есть Сигнал? | Маска | Обработчик |
---|---|---|---|
1 | 1 | 1 | SIG_DFL |
2 | 0 | 0 | SIG_IGN |
3 | 0 | 0 | sig_func() |
. | . | . | . |
- Есть сигнал? — битовое поле, указывающее наличие недоставленного сигнала
- Маска — битовое поле, указывающее временный запрет на доставку сигнала
- Обработчик — указатель на действие, выполняемое при доставке сигнала. Может принимать значения: SIG_DFL — действие по умолчанию, SIG_IGN — игнорирование сигнала или указатель на функцию — обработчика сигнала.
Традиционно, при отправке процессу нескольких однотипных обычных сигналов, обработчик будет вызван лишь раз. Начиная с POSIX 1003.1, кроме обычных сигналов, поддерживаются сигналы реального времени, для которых создаётся очередь недоставленных сигналов, которая кроме номера сигнала, содержит значение (целое или адрес), которое уникально для каждого экземпляра сигнала.
Примеры использования сигналов
SIGKILL, SIGTERM, SIGINT, SIGHUP — завершение процесса. SIGKILL — не может быть проигнорирован, остальные могут. SIGTERM — оповещение служб о завершении работы ОС, SIGINT — завершение программы по нажатию Ctrl C, SIGHUP — оповещение программ, запущенных через модемное соединение, об обрыве связи (в настоящее время практически не используется).
SIGILL, SIGFPE, SIGBUS, SIGSEGV — аппаратный сбой. SIGILL — недопустимая инструкция CPU, SIGFPE — ошибка вычислений с плавающей точкой (деление на ноль), SIGBUS — физический сбой памяти, SIGSEGV — попытка доступа к несуществующим (защищенным) адресам памяти.
SIGSTOP, SIGCONT — приостановка и продолжение выполнения процесса
SIGPIPE — попытка записи в канал или сокет, у которого нет читателя
SIGCHLD — оповещение о завершении дочернего процесса.
Список сигналов
Особый сигнал с номером 0 фактически не доставляется, а используется в вызове kill() для проверки возможности доставки сигнала определённому процессу.
В Linux используется 64 сигнала. Список можно посмотреть в терминале командой kill -l
Posix.1-1990
Источник — man 7 signal
Отправка сигнала
int kill(pid_t pid, int signum);
Для отправка сигнала необходимо, чтобы uid или euid текущего процесса был равен 0 или совпадал с uid процесса получателя.
Получатель сигнала зависит от величины и знака параметра pid :
- pid > 0 — сигнал отправляется конкретному процессу
- pid == 0 — сигнал отправляется всем членам группы
- pid == -1 — сигнал отправляется всем процессам кроме init (в Linux’е еще кроме себя)
- pid int sigqueue(pid_t pid, int sig, const union sigval value);
Аналогично kill() , но выполняется по правилам сигналов реального времени. Сигнал и связанная с ним дополнительная информация (целое или адрес) value помещаются в очередь сигналов (FIFO). Таким образом процессу можно отправить несколько однотипных сигналов с разными значениями value .
Отправка сигнала текущему процессу. Эквивалент kill(getpid(),signum);
Убирает из маски сигналов сигнала SIGABRT и отправляет его текущему процессу . Если сигнал перехватывается или игнорируется, то после возвращения из обработчика abort() завершает программу. Выхода из функции abort() не предусмотрено. Единственный способ продолжить выполнение — не выходить из обработчика сигнала.
Отправка сигнала SIGALRM себе через time секунд. Возвращает 0 если ранее alarm не был установлен или число секунд остававшихся до срабатывания предыдущего alarma. Таймер управляющий alarm’ами один. Соответственно установка нового alarm’а отменяет старый. Параметр time==0 позволяет получить оставшееся до alarm’а время без установки нового.
Исторический способ обработки сигнала — signal
Установка реакции на сигнал через функцию signal() не до конца стандартизована и сохраняется для совместимости с историческими версиями Unix. Не рекомендуется к использованию. В стандарте POSIX signal() заменен на вызов sigaction(), сохраняющий для совместимости эмуляцию поведения signal().
sighandler — адрес функции обработчика void sighandler(int) или один из двух макросов: SIG_DFL (обработчик по умолчанию) или SIG_IGN (игнорирование сигнала).
signal(. ) возвращает предыдущее значение обработчика или SIG_ERR в случае ошибки.
В Linux и SysV при вызове sighandler обработчик сбрасывается в SIG_DFL и возможна доставка нового сигнала во время работы sighandler . Такое поведение заставляет первой строкой в sighandler восстанавливать себя в качестве обработчика сигнала, и, даже в этом случае, не гарантирует от вызова обработчика по умолчанию. В BSD системах сброс не происходит, доставка новых сигнала блокируется до выхода из sighandler .
Реакция на сигнал — sigaction
Параметры для установки обработчика сигнала через sigaction()
Данные, передаваемые в обработчик сигнала sa_sigaction()
В Linux структура siginfo_t содержит больше полей, но они служат для совместимости и не заполняются.
Блокирование сигналов
Все функции блокирования сигналов работают с маской сигналов типа sigset_t. В Linux это 64 бита, т.е. два слова в 32х разрядной архитектуре или одно в 64х разрядной. Выставленный бит в маске сигналов означает, что доставка сигнала с соответствующим номером будет заблокирована. Сигналы SIGKILL и SIGSTOP заблокировать нельзя.
Манипулирование маской
Параметр how определяет операцию над текущей маской. Значения SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK.
Проверка наличия заблокированных сигналов
Очистка заблокированных сигналов
sigwait ожидает блокировки какого-либо из сигналов, указанных в маске, удаляет этот сигнал и возвращает его номер в параметр sig . Если реализация сигналов предусматривает очередь сигналов, то удаляется только один элемент из очереди.
Управляющий терминал, сеанс, группы
Управляющий терминал, сеанс, группы
Для организации диалоговой работы пользователей в Unix вводится понятие терминальной сессии. С точки зрения пользователя — это процесс работы с текстовым терминалом с момента ввода имени и пароля и до выхода из системы командой logout ( exit , нажатие ^D в пустой строке). Во время терминальной сессии может быть запущено несколько программ, которые будут параллельно выполнятся в фоновом режиме и между которыми можно переключаться в диалоговом режиме. После завершения терминальной сессии возможно принудительное завершение всех запущенных в ней фоновых процессов.
С точки зрения ядра — терминальная сессия — это группа процессов, имеющих один идентификатор сеанса sid. С идентификатором sid связан драйвер управляющего терминала, доступный всем членам сеанса как файл символьного устройства /dev/tty. Для каждого сеанса существует свой /dev/tty. Управляющий терминал взаимодействует с процессами сеанса с помощью отправки сигналов.
В рамках одного сеанса могут существовать несколько групп процессов. С каждым процессом связан идентификатор группы pgid. Одна из групп в сеансе может быть зарегистрирована в драйвере управляющего терминала как группа фоновых процессов. Процессы могут переходить из группы в группу самостоятельно или переводить из группы в группу другие процессы сеанса. Перейти в группу другого сеанса нельзя, но можно создать свой собственный сеанс из одного процесса со своей группой в этом сеансе. Вернуться в предыдущий сеанс уже не получится.
Группа процессов
Группа процессов — инструмент для доставки сигнала нескольким процессам, а также способ арбитража при доступе к терминалу. Идентификатор группы pgid равен pid создавшего её процесса — лидера группы. Процесс может переходить из группы в группу внутри одного сеанса.
Сеанс
Сеанс — средство для контроля путем посылки сигналов над несколькими группами процессов со стороны терминального драйвера. Как правило соответствует диалоговой пользовательской сессии. Идентификатор сеанса sid равняется идентификатору pid, создавшего его процесса — лидера сеанса. Одновременно с сеансом создаётся новая группа с pgid равным pid лидера сеанса. Поскольку переход группы из сеанса в сеанс невозможен, то создающий сеанс процесс не может быть лидером группы.
Создание собственного сеанса рекомендуется начать с fork, чтобы гарантировать, что процесс не является лидером группы.
Фоновая группа сеанса
Процессы в фоновой группе выполняются до тех пор, пока не попытаются осуществить чтение или запись через файловый дескриптор управляющего терминала. В этот момент они получают сигнал SIGTTIN или SIGTTOU соответственно. Действие по умолчанию для данного сигнала — приостановка выполнения процесса.
Назначение фоновой группы:
Управляющий терминал
Некоторые сочетания клавиш позволяют посылать сигналы процессам сеанса:
- ^C — SIGINT — завершение работы
- ^Z — SIGTSTP — приостановка выполнения. bash отслеживает остановку дочерних процессов и вносит их в списки своих фоновых процессов. Остановленный процесс может быть продолжен командой fg n , где n — порядковый нрмер процесса в списке фоновых процессов
Источник
Что такое sig linux
Сигналы являются программными прерываниями, которые посылаются процессу, когда случается некоторое событие. Сигналы могут возникать синхронно с ошибкой в приложении, например 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) : «);
Источник