В общем, чтобы убить процессы, мы генерируем сигналы вроде SIGKILL
и SIGTSTP
т. Д.
Но как узнать, кто заказал этот конкретный сигнал, кто отправил его определенному процессу, и вообще, как сигналы выполняют свои операции? Как внутренние сигналы работают?
kill
signals
architecture
Варун Чхангани
источник
источник
Ответы:
50000 футов вид это то, что:
Сигнал генерируется либо внутренним ядром (например,
SIGSEGV
при обращении к недопустимому адресу, илиSIGQUIT
когда вы нажимаете Ctrl+ \), либо программой, использующейkill
системный вызов (или несколько связанных).Если это один из системных вызовов, то ядро подтверждает, что вызывающий процесс имеет достаточные привилегии для отправки сигнала. Если нет, возвращается ошибка (и сигнал не происходит).
Если это один из двух специальных сигналов, ядро безоговорочно действует на него, без какого-либо участия целевого процесса. Два специальных сигнала - SIGKILL и SIGSTOP. Все нижеприведенное о действиях по умолчанию, блокирующих сигналах и т. Д. Не имеет значения для этих двух.
Далее ядро выясняет, что делать с сигналом:
Для каждого процесса есть действие, связанное с каждым сигналом. Есть куча по умолчанию, и программы могут устанавливать различные те , используя
sigaction
,signal
и т.д. Они включают в себя такие вещи , как «игнорировать его полностью», «убить процесс», «убить процесс с дампом памяти», «остановить процесс», и т.п.Программы также могут отключить доставку сигналов («заблокированных»), по каждому сигналу. Затем сигнал остается в ожидании, пока не разблокируется.
Программы могут запросить, чтобы вместо того, чтобы ядро выполняло какое-то действие самостоятельно, оно доставляло сигнал процессу либо синхронно (с
sigwait
, и т. Д. Илиsignalfd
), либо асинхронно (прерывая все, что делает процесс, и вызывая указанную функцию).Существует второй набор сигналов, называемых «сигналами в реальном времени», которые не имеют конкретного значения и также позволяют ставить в очередь несколько сигналов (обычные сигналы ставятся в очередь только по одному из каждого, когда сигнал блокируется). Они используются в многопоточных программах для потоков, чтобы общаться друг с другом. Некоторые из них используются, например, в реализации потоков POSIX в glibc. Они также могут использоваться для связи между различными процессами (например, вы можете использовать несколько сигналов в реальном времени, чтобы программа fooctl отправляла сообщение демону foo).
Для просмотра не 50 000 футов попробуйте
man 7 signal
также и внутреннюю документацию ядра (или источник).источник
Реализация сигнала очень сложна и специфична для ядра. Другими словами, разные ядра будут реализовывать сигналы по-разному. Упрощенное объяснение состоит в следующем:
ЦП, основанный на специальном значении регистра, имеет адрес в памяти, где он ожидает найти «таблицу дескрипторов прерываний», которая на самом деле является векторной таблицей. Существует один вектор для каждого возможного исключения, например деление на ноль, или ловушка, как INT 3 (отладка). Когда ЦП встречает исключение, он сохраняет флаги и текущий указатель команд в стеке, а затем переходит на адрес, указанный соответствующим вектором. В Linux этот вектор всегда указывает на ядро, где есть обработчик исключений. Процессор теперь готов, а ядро Linux вступает во владение.
Обратите внимание, что вы также можете вызвать исключение из программного обеспечения. Например, пользователь нажимает CTRL- C, затем этот вызов переходит к ядру, которое вызывает собственный обработчик исключений. В общем, есть разные способы добраться до обработчика, но независимо от того, что происходит одна и та же базовая вещь: контекст сохраняется в стеке, а обработчик исключений ядра переходит к нему.
Затем обработчик исключений решает, какой поток должен получить сигнал. Если произошло что-то вроде деления на ноль, то это легко: поток, вызвавший исключение, получает сигнал, но для других типов сигналов решение может быть очень сложным, а в некоторых необычных случаях более или менее случайный поток может получить сигнал.
Чтобы отправить сигнал, то, что делает ядро, сначала устанавливает значение, указывающее тип сигнала
SIGHUP
или что-то еще. Это просто целое число. Каждый процесс имеет область памяти «ожидающий сигнал», где хранится это значение. Затем ядро создает структуру данных с информацией о сигнале. Эта структура включает сигнал «расположение», который может быть по умолчанию, игнорировать или обрабатывать. Затем ядро вызывает свою собственную функциюdo_signal()
. Следующий этап начинается.do_signal()
сначала решает, будет ли он обрабатывать сигнал. Например, если это убийство , тоdo_signal()
просто убивает процесс, конец истории. В противном случае он смотрит на диспозицию. Если расположение по умолчанию, тоdo_signal()
обрабатывает сигнал в соответствии с политикой по умолчанию, которая зависит от сигнала. Если расположение является дескриптором, то это означает, что в пользовательской программе есть функция, предназначенная для обработки рассматриваемого сигнала, и указатель на эту функцию будет находиться в вышеупомянутой структуре данных. В этом случае do_signal () вызывает другую функцию ядра,handle_signal()
, который затем проходит процесс переключения обратно в режим пользователя и вызова этой функции. Детали этой передачи чрезвычайно сложны. Этот код в вашей программе обычно автоматически связывается с вашей программой, когда вы используете функции вsignal.h
.Посредством надлежащего изучения значения ожидающего сигнала ядро может определить, обрабатывает ли процесс все сигналы, и примет соответствующие меры, если это не так, что может перевести процесс в режим сна или убить его или другое действие, в зависимости от сигнала.
источник
Хотя на этот вопрос дан ответ, позвольте мне опубликовать подробный поток событий в ядре Linux.
Это полностью скопировано из постов Linux: Linux Signals - Internals в блоге «Посты Linux» на sklinuxblog.blogspot.in.
Программа "Пространство пользователя сигнала C"
Давайте начнем с написания простой программы для пользователя на языке C:
Этот код назначает новый обработчик для сигнала SIGINT. SIGINT может быть отправлен в рабочий процесс с помощью комбинации клавиш Ctrl+ C. При нажатии Ctrl+ Cна задание отправляется асинхронный сигнал SIGINT. Это также эквивалентно отправке
kill -INT <pid>
команды в другой терминал.Если вы сделаете
kill -l
(это строчная букваL
, что означает «список»), вы узнаете различные сигналы, которые могут быть отправлены в работающий процесс.Также следующая комбинация клавиш может использоваться для отправки определенных сигналов:
Если вы скомпилируете и запустите вышеуказанную программу на C, вы получите следующий вывод:
Даже с Ctrl+ Cили
kill -2 <pid>
процесс не закончится. Вместо этого он выполнит обработчик сигнала и вернется.Как сигнал отправляется в процесс
Если мы увидим внутреннюю часть сигнала, отправляемого процессу, и поместим Jprobe с dump_stack в
__send_signal
функцию, то увидим следующую трассировку вызова:Таким образом, основные вызовы функций для отправки сигнала выглядят так:
Теперь все настроено и необходимые изменения внесены
task_struct
в процесс.Обработка сигнала
Сигнал проверяется / обрабатывается процессом, когда он возвращается из системного вызова или если выполняется возврат из прерывания. Возврат из системного вызова присутствует в файле
entry_64.S
.Функция int_signal вызывается функцией, из
entry_64.S
которой вызывается функцияdo_notify_resume()
.Давайте проверим функцию
do_notify_resume()
. Эта функция проверяет, установлен ли у насTIF_SIGPENDING
флаг вtask_struct
:СИСТЕМНЫЕ звонки и сигналы
«Медленные» системные вызовы, например, блокировка чтения / записи, перевод процессов в состояние ожидания:
TASK_INTERRUPTIBLE
илиTASK_UNINTERRUPTIBLE
.Задание в состоянии
TASK_INTERRUPTIBLE
будет изменено наTASK_RUNNING
состояние по сигналу.TASK_RUNNING
означает, что процесс может быть запланирован.В случае выполнения его обработчик сигнала будет запущен до завершения «медленного» системного вызова. По
syscall
умолчанию не завершается.Если
SA_RESTART
флаг установлен,syscall
перезапускается после завершения обработчика сигнала.Ссылки
источник
kill
команду, которая является встроенной в оболочку). (2c) Хотя точки с запятой после закрытия}
функции, строго говоря, не являются ошибками, они не нужны и крайне неортодоксальны. (3) Даже если бы все было правильно, это не было бы очень хорошим ответом на вопрос. (3a) Вопрос, хотя и несколько неясный, по-видимому, сосредоточен на том, как субъекты (пользователи и процессы) инициируют (т.е. отправляют ) сигналы. … (Продолжение)