Как послать сигнал процессу linux

Обновлено: 03.07.2024

  • Родительский процесс запускает дочерний процесс для выполнения задачи — возможно, дочерний процесс выполняет бесконечный цикл — и затем завершает дочерний процесс, когда задача больше не нужна.
  • Процесс выполняется как часть группы и должен завершить или уведомить другие процессы в группе при возникновении ошибки или другого события.
  • Два процесса должны синхронизироваться при совместной работе.

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

Функция уничтожения объявлена ​​в signal.h.

Функция: int kill (pid_t pid , int signum )

Предварительно: | МТ-Сейф | AS-безопасный | AC-безопасный | См. раздел «Концепции безопасности POSIX».

Функция kill отправляет знак сигнала процессу или группе процессов, указанной в pid . Помимо сигналов, перечисленных в Стандартных сигналах, signum также может иметь нулевое значение для проверки достоверности pid .

Pid указывает процесс или группу процессов для получения сигнала:

Процесс с идентификатором pid . (В Linux сигнал отправляется всему процессу, даже если pid — это идентификатор потока, отличный от идентификатора процесса.)

Все процессы в той же группе процессов, что и отправитель.

Группа процессов с идентификатором - pid .

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

Процесс может отправить сигнал самому себе с помощью такого вызова, как kill (getpid(), signum ). Если kill используется процессом для отправки сигнала самому себе, и сигнал не заблокирован, то kill доставляет по крайней мере один сигнал (который может быть другим ожидающим разблокированным сигналом вместо signal signum ) этому процессу, прежде чем он вернется.

Возвращаемое значение kill равно нулю, если сигнал может быть отправлен успешно. В противном случае сигнал не посылается и возвращается значение -1. Если pid указывает отправку сигнала нескольким процессам, kill завершается успешно, если он может отправить сигнал хотя бы одному из них. Невозможно сказать, какой из процессов получил сигнал или все ли они.

Для этой функции определены следующие условия ошибки:

Аргумент signum является недопустимым или неподдерживаемым числом.

У вас нет права отправлять сигнал процессу или любому из процессов в группе процессов с именем pid .

Аргумент pid не относится к существующему процессу или группе.

Функция: int tgkill (pid_t pid , pid_t tid , int signum )

Предварительно: | МТ-Сейф | AS-безопасный | AC-безопасный | См. раздел «Концепции безопасности POSIX».

Функция tgkill отправляет знак сигнала потоку или процессу с идентификатором tid , как и функция kill, но только если идентификатор процесса потока tid равен pid . Если целевой поток принадлежит другому процессу, функция завершается с ошибкой ESRCH .

Функция tgkill может использоваться, чтобы избежать отправки сигнала потоку в неправильном процессе, если вызывающая сторона гарантирует, что переданное значение pid не будет повторно использоваться ядром (например, если это идентификатор текущего процесса). , возвращаемый getpid ).

Функция: int killpg (int pgid , int signum )

Предварительно: | МТ-Сейф | AS-безопасный | AC-безопасный | См. раздел «Концепции безопасности POSIX».

Это похоже на kill , но посылает сигнал группе процессов pgid . Эта функция предусмотрена для совместимости с BSD; использование kill для этого более переносимо.

В качестве простого примера kill вызов kill (getpid(), sig) имеет тот же эффект, что и raise (sig).

Команда kill в UNIX позволяет пользователю отправить сигнал процессу. Сигнал — это сообщение, отправленное процессу, чтобы прервать его и вызвать ответ. Если процесс был спроектирован так, чтобы реагировать на сигналы такого типа, он так и делает; в противном случае он завершается. В следующей таблице перечислены некоторые часто используемые номера/имена сигналов и их значения.

Убить (заканчивается без очистки)

Работает, только если выдано владельцем процесса или суперпользователем (root)

Программа не может реагировать на этот сигнал; он должен прекратиться

Убить (закончено после очистки)

Работает, только если выдано владельцем процесса или суперпользователем (root)

Элемент меню Kill позволяет быстро завершить процесс, отправив ему сигнал kill (9). Пункт меню «Сигнал» дает вам больший контроль над сигналом, посылаемым командой kill(1). Например, вы можете послать сигнал INT или сигнал HUP и т. д.

Отправлять сигнал процессу следует только в том случае, если вы понимаете последствия этого. Например, если вы выберете оболочку входа в систему и отправите сигнал уничтожения, вы внезапно выйдете из системы.Дополнительную информацию о процессах и управлении заданиями можно получить у системного администратора или в Руководстве для опытных пользователей Solaris (Sun Microsystems).

Завершение процесса (быстрое удаление)

Выберите запись процесса на панели прокрутки диспетчера процессов.

Выберите «Убить» в меню «Процесс».

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

Эквивалентная команда UNIX:

kill -9 PID, где PID — это идентификатор выбранного процесса.

Вы можете переопределить команду, выполняемую пунктом меню "Убить", на другую команду, переопределив действие с пометкой "Убить" в файле:

Отправить сигнал процессу

Выберите запись процесса на панели прокрутки диспетчера процессов.

Выберите «Сигнал» в меню «Процесс».

Диспетчер процессов отображает диалоговое окно с просьбой указать сигналы. Вы должны указать хотя бы один из 42 сигналов, определенных на справочной странице signal(5).

Введите номер или имя соответствующего сигнала и нажмите OK.

Диспетчер процессов выдает сигнальную команду и закрывает диалоговое окно. Сообщение об успехе не выдается. Уничтожение процесса обычно приводит к уничтожению его потомков.

Эквивалентная команда UNIX: kill -signum_name PID

где -signum_name — номер или имя сигнала, а PID — идентификатор выбранного процесса.

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

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

xclock получает сигнал номер 15 от bash

Однако существуют разные виды сигналов. Различные вкусы имеют символические имена, но также идентифицируются целыми числами. Различные целые числа и символические имена, которым они сопоставлены, могут быть перечислены с помощью команды kill -l или просмотрены на справочной странице signal.

Linux, как и большинство версий Unix, реализует 32 "обычных" сигнала. В Linux сигналы с номерами от 32 до 64 (которые не являются стандартными для различных версий Unix) являются сигналами «реального времени».

Почему отправляются сигналы?

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

Исключения оборудования

Процесс запросил аппаратное обеспечение для выполнения какой-то ошибочной операции. Например, ядро ​​отправит процессу SIGFPE (сигнал номер 8), если он выполнит деление на 0.

Условия использования программного обеспечения

Возможно, процессы должны быть уведомлены о каком-либо ненормальном состоянии программного обеспечения. Например, всякий раз, когда процесс умирает, ядро ​​отправляет SIGCHLD (сигнал номер 17) родителю процесса. В качестве другого примера, графические приложения X получают SIGWINCH (сигнал номер 28) всякий раз, когда изменяется размер их окна, чтобы они могли реагировать на новую геометрию.

Прерывания терминала

Различные последовательности клавиш управления терминалом отправляют сигналы процессу переднего плана оболочки bash. Например, CTRL-C отправляет SIGINT (сигнал номер 2), а CTRL-Z отправляет SIGTSTP (сигнал номер 20).

Другие процессы

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

Отправка сигналов: команда kill

Команда kill используется для доставки пользовательских сигналов другим процессам. Ожидается, что он будет вызываться с помощью числового или символического переключателя командной строки, который указывает, какой сигнал отправлять, и идентификатора процесса, который указывает, какой процесс должен его получить. Например, следующие команды передают сигнал SIGCHLD (сигнал номер 17) процессу xclock с идентификатором процесса 8060.

При использовании символического имени для указания сигнала префикс «SIG» (который используется всеми сигналами) может быть включен или опущен.

Получение сигналов

Когда процесс получает сигнал, он может выполнить одно из следующих трех действий.

1. Реализовать обработчик сигналов ядра по умолчанию

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

Справочная страница «signal» документирует, какое поведение соответствует какому сигналу.

2. Выберите «Игнорировать сигнал»

Программисты могут выбрать для своего приложения простое игнорирование определенных сигналов.

3. Выберите реализацию пользовательского обработчика сигналов

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

Использование сигналов для завершения процессов

Из 32 сигналов, используемых в Linux (и Unix), обычные пользователи на практике (явно) используют только несколько.

Число Символ Действие
2 SIGINT Прерывание (запрос завершения) процесса. Это сигнал, сгенерированный управляющей последовательностью CTRL-C.
9 SIGKILL Принудительное завершение процесса (это сигнал не может быть переопределен процессом).
15 SIGTERM Запрос на завершение процесса.
20 SIGTSTP Остановить (приостановить) процесс. Это сигнал, генерируемый управляющей последовательностью CTRL-Z.

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

Например, Эйнштейн запустит команду cat, которая в принципе будет выполняться вечно. Затем он отслеживает идентификатор процесса команды и завершает ее с помощью SIGTERM.

SIGTERM (сигнал номер 15) — это сигнал по умолчанию для команды kill, поэтому Эйнштейн мог бы использовать команду kill 8375 для того же эффекта. Далее Эйнштейн повторяет последовательность, на этот раз отправляя сигнал SIGKILL.

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

Команда pkill

В каждом из предыдущих примеров Эйнштейну необходимо определить идентификатор процесса перед отправкой ему сигнала с помощью команды kill. Команду pkill можно использовать для отправки сигналов процессам, выбранным более общими средствами. Команда pkill предполагает следующий синтаксис.

Первый токен дополнительно указывает номер сигнала для отправки (по умолчанию номер сигнала 15). ШАБЛОН — это расширенное регулярное выражение, которое будет сравниваться с именами команд. В следующей таблице перечислены часто используемые параметры командной строки. Процессам, которые соответствуют всем указанным критериям, будет отправлен указанный сигнал.

< td>-t TERM
Переключить Эффект
-n Выбрать только самые новые (самые недавно запущенный) соответствующий процесс.
-u USER Выберите процессы, принадлежащие пользователю USER.
Выбрать процессы, контролируемые терминалом TERM.

Для удобства команда pkill опускает себя и запустившую ее оболочку при уничтожении всех процессов, принадлежащих конкретному пользователю или терминалу. Рассмотрим следующий пример.

Обратите внимание, что, хотя оболочка bash считается процессом, принадлежащим пользователю maxwell, она пережила резню.

Команда killall

Подобно pkill, команда killall доставляет сигналы процессам, указанным в имени команды. Команда killall поддерживает следующие параметры командной строки.

Главная команда

Команду top также можно использовать для передачи сигналов процессам. При нажатии клавиши K над списком процессов появляется следующее диалоговое окно, позволяющее пользователю указать, идентификатор какого процесса должен получать сигнал, а какой — доставлять.

Я пытаюсь понять справочную страницу программы dd, в которой упоминается:

Отправка сигнала USR1 запущенному процессу dd заставляет его печатать статистику ввода-вывода в стандартную ошибку, а затем возобновлять копирование.

Что значит pid=$! в смысле?

Это присвоение переменной, которая получает pid dd ?И в итоге используется в переменной $pid?

Кроме того, почему они используют сон и убийство ?

Это способ использования -USR1 ?


не ответ на понимание dd, но вы видели pv? например: dd if=/dev/zero | пв | dd of=/dev/null, он также поддерживает индикатор выполнения.

3 ответа 3

дд, если=/dev/zero of=/dev/null&

Значок & в конце означает выполнение префиксной команды в фоновом режиме. (Отказ от ответственности: это упрощенное утверждение)

$! это PID самой последней фоновой команды.

Итак, pid=$! назначьте самый последний фоновый PID переменной pid, которая является dd PID.

Кроме того, почему они используют sleep и kill?.

Вам нужно kill $pid (если параметр не указан, сигналом по умолчанию для kill является TERM, то есть завершение процесса), чтобы завершить процесс dd после завершения тестирования, иначе процесс dd может просто остаться в фоновом режиме и исчерпать ресурсы вашего процессора. Проверьте системный монитор вашей платформы, чтобы увидеть это.

В то время как команда Kill -USR1 $pid выводит статистику ввода-вывода, она не завершает процесс.

Без сна в течение 1 секунды ваш процесс dd может быть остановлен последним оператором команды kill $pid ** до того, как он сможет записать вывод статистики на ваш терминал. Процессы синхронны, но операция trap+write ( kill -USR1 $pid ) может быть медленнее, чем операция завершения ( kill $pid ). Так что спите 1 секунду, чтобы отложить запуск kill $pid, чтобы убедиться, что вывод статистики завершен.

Отправка сигнала USR1 запущенному процессу dd заставляет его печатать статистику ввода-вывода в стандартную ошибку, а затем возобновлять копирование.

И человек 7 сигнал :

Объединив оба оператора, вы должны понимать, что USR1 — это сигнал, определяемый пользователем, который определяется dd, чтобы предоставить пользователю возможность прервать его и распечатать статистику ввода-вывода на лету. Это специфичный для программы обработчик, это не означает, что вы можете убить -USR1 other_program_pid и ожидать вывода статистики.


Это просто демонстрация использования сигнала USR1 с dd .

запускает dd в фоновом режиме, копируя данные из /dev/zero (который создает нули всякий раз, когда программа читает из него) в /dev/null (который отбрасывает все, что в него записано). Это обеспечивает безобидный экземпляр dd, который можно использовать для экспериментов — он не использует память и будет продолжать работать столько, сколько мы захотим, что дает пользователю время для отправки ему сигналов.

сохраняет идентификатор процесса последней фоновой команды ( $! ) в переменной pid .

отправляет сигнал USR1 процессу, идентификатором которого является значение, хранящееся в переменной pid, в данном случае фоновой dd. Когда dd получает этот сигнал, он распечатывает свой текущий прогресс (количество прочитанных и записанных данных) и продолжает копирование.

ждет одну секунду.

отправляет сигнал TERM в dd , что приводит к завершению работы dd. (Нет смысла оставлять фоновый dd здесь запущенным.)

Было бы поучительнее запустить это вместо второй строки выше:

Это выведет ход выполнения дважды, с интервалом в одну секунду, чтобы показать ход выполнения dd; затем убейте dd, не дожидаясь.

Для реального использования вы должны указать соответствующие входные и выходные данные для исходной команды dd и, возможно, некоторые другие параметры, и вы не будете запускать last kill — вы будете ждать, пока dd завершит работу сама по себе. .

Чтобы ответить на ваш последний вопрос, вот как вы отправляете сигналы USR1 из оболочки (или любой другой сигнал): вы используете kill с сигналом, который хотите отправить, и идентификаторы процессов (или идентификаторы заданий) процессов, которые вы хотите отправить сигнал. Другие (не POSIX) команды, которые вы можете использовать, это pkill и killall , когда вы хотите найти процессы по имени.

Для большинства или всех оболочек $! - это идентификатор процесса (также называемый PID) последнего процесса, который разветвляется оболочкой. Команда dd была разветвлена ​​с & , так что pid=$! сразу после разветвления dd присваивает идентификатор процесса dd переменной оболочки pid .

Идентификатор процесса – это число, используемое Linux или Unix для обозначения адресного пространства, в котором выполняется некоторый код.

У программы kill неинтуитивное название, потому что ее цель — посылать сигналы (небольшие асинхронные сообщения) процессам. Сигналов всего несколько, всего может быть 128, у них есть и номера, и названия. Например, сигнал «убить» — это номер 9. USR1 определяется как номер 10. Таким образом, команда kill -USR1 $pid отправляет сигнал 10 процессу с номером $pid. Выполнение dd иногда занимает много времени, поэтому почти наверняка это идентификатор процесса команды dd, которая была разветвлена ​​ранее и выполнялась в фоновом режиме. Команда kill $pid отправляет сигнал TERM тому же идентификатору процесса. ТЕРМИН означает «прекращение».Хорошо написанные программы обычно ловят TERM, очищают выделенные ресурсы и затем завершают работу.

Я не совсем понимаю, зачем запускать dd в фоновом режиме, посылать ему сигнал USR1, ждать 1 секунду, а затем заставлять dd освобождать все ресурсы и выходить. Весь фрагмент кода, кажется, предполагает, что dd работает в течение длительного времени, что может быть неправдой. Я думаю, что в этом коде есть условия гонки, и какой бы ни была желаемая семантика, на самом деле вы можете их не получить.

Читайте также:

Switch Effect
-i, –interactive Интерактивный запрос пользователь перед отправкой сигнала процессу.
-w, --wait Подождите, пока все процессы не будут уничтожены перед возвратом.