LXF131:DrBrown3
|
|
|
Содержание |
Шлем верные сигналы
- Сигналы Подробное руководство о том, что это, откуда они взялись, куда идут и что происходит при отправке.
Сигнал – событие, отправляемое выполняющейся программе ядром или пользовательским процессом. Сигналы асинхронны, то есть могут приходить когда угодно, и их появление в большинстве случаев никак не связано с тем, что собиралась делать программа. Сигналы обычно означают некое внешнее событие, способное повлиять на выполнение программы. Программа может выбрать, что должно произойти по приходу сигнала определенного типа. Она может игнорировать его (за одним важным исключением); запустить специальный обработчик сигнала и продолжить с того места, где остановилась; или просто выполнить «действие по умолчанию» для этого сигнала, что в большинстве случаев означает завершение процесса.
За исключением сигналов «реального времени», существует 31 тип сигнала. Каждый тип определяется именем (например, SIGTERM) и целым числом (например, 15). Получить список всех типов можно командой:
$ kill -l
Из этих 31 администратор должен знать, полагаю, шесть. Я свел их в таблицу.
Имя | № | Описание | Действие по умолчанию |
---|---|---|---|
SIGHUP | 1 | Инициирует перенастройку фонового сервиса | Завершить процесс |
SIGINT | 2 | Ctrl+C с клавиатуры | Завершить процесс |
SIGQUIT | 3 | Ctrl+\ с клавиатуры | Завершить процесс с дампом памяти |
SIGKILL | 9 | Суперважный сигнал, который нельзя перехватить или игнорировать | Завершить процесс |
SIGSEGV | 11 | Программа пыталась обратиться к памяти по неверному адресу | Завершить процесс с дампом памяти |
SIGTERM | 15 | «Вежливая» просьба закончить работу | Завершить процесс |
Сигнал SIGHUP обычно используется для предупреждения демона (это системный сервис, работающий в фоне), что конфигурационный файл изменен и его нужно перечитать. Многие демоны так и реагируют на SIGHUP. Примеры включают «суперсервер Интернета» xinetd и демон системного журнала syslogd. Демонам, поддерживающим SIGHUP, лучше отправить этот сигнал, чем перезапустить их – тогда существующие соединения с клиентами сохранятся, а при останове и перезапуске демона они будут разорваны.
«HUP» – сокращение от «hang up» (повесить трубку). Изначально этот сигнал генерировался драйвером терминала последовательного порта с подключенным на прием звонков модемом. Если телефонное соединение обрывалось, драйвер терминала замечал, что несущая исчезла, и отправлял SIGH-UP оболочке, завершая ее. Идея состояла в том, чтобы гарантировать, что новый абонент не начнет случайно работать в оболочке предыдущего.
Сигнал SIGINT посылается активному процессу при нажатии Ctrl+C в его терминале. Его действие по умолчанию – завершить (убить) процесс. Поэтому «долгоиграющие» задания часто можно прервать, нажав Ctrl+C. Однако многие программы игнорируют или перехватывают SIGINT. Например, less при получении SIGINT не завершается, а запрашивает ввод команды.
Сигнал SIGQUIT посылается активному процессу при нажатии Ctrl+\ на клавиатуре. Он используется гораздо реже и менее известен, чем SIGINT. По умолчанию он также завершает процесс, но заодно заставляет оболочку создать файл core, содержащий образ памяти программы, для «посмертной» отладки. В большинстве дистрибутивов файлы core запрещены, потому что в настройке процесса ulimit (которая ограничивает использование ресурсов) максимальный размер файла core установлен в ноль. Чтобы проверить свои настройки, выполните команду ulimit -a и поищите встроенную команду ulimit на man-странице bash.
Смертоносные сигналы
Сигнал SIGTERM отправляется командой kill по умолчанию. Это вежливая просьба «пожалуйста, приберите за собой и завершитесь». При выключении системы процесс init отправляет сигналы SIGTERM всем выполняющимся процессам с просьбой завершиться. Если это не срабатывает, init применяет более суровые меры...
Сигнал SIGKILL – самый подлый из всех. Его нельзя перехватить или игнорировать, и его действие – прикончить процесс. Отправка SIGKILL должна быть крайней мерой, только в том случае, если более благородные SIGTERM и SIGINT не сработали. Разница между SIGTERM и SIGKILL – как между вежливой просьбой завершиться и выстрелом в голову. SIGKILL не дает процессу возможности прибраться. Перед перезапуском «убитых» программ, которые временно хранили данные на диске или находились посреди двухфазной фиксации транзакции, может потребоваться ручная расчистка.
Сигнал SIGSEGV (нарушение сегментации) отличается от прочих описанных здесь тем, что не приходит извне, а обусловлен самой программой. Он подается, когда программа пытается обратиться к адресу памяти вне отведенного ей диапазона. (Это легко сделать в C и C++, сославшись на неинициализированный указатель). Блок управления памятью видит эту попытку и тихо говорит ядру, которое отправляет SIGSEGV программе. Действие по умолчанию при получении этого сигнала – завершить программу. Если в программе нет ошибок, такого произойти не должно, но безупречных программ мало, и вы, наверное, видели, как программы падают из-за ошибки нарушения сегментации.
Сигналы SIGILL (неверная команда), SIGBUS (ошибка шины) и SIGFPE (исключение с плавающей точкой) генерируются подобным образом, когда программа пытается сделать такое, чего не разрешает аппаратная часть; но распространены они гораздо меньше. SIGSEGV легко продемонстрировать. Следующая программа на С из двух строк генерирует этот сигнал в ответ на попытку записать число по адресу памяти 0:
main() { *((int*)0) = 0;}
История о SIGSEGV
В первый раз я общался с Unix в так называемой "Edition6". Я принес на работу копию, которую мне дал коллега в Открытом университете, и установил ее на наш PDP-11/60. На другой день я печатал некоторые man-страницы (другой печатной документации не было) и получил сообщение об «ошибке памяти». Решив, что компьютер неисправен, я выключил Unix и провел остаток дня за диагностикой оборудования, но никаких проблем не обнаружил. В конце концов я узнал, что «ошибка памяти» – это сообщение оболочки о том, что процесс завершился с SIGSEGV. Со временем я выяснил, что многие сообщения об ошибках в Unix были скорее причудами программиста, а не попыткой объяснить, что же на самом деле происходит. Моим любимым было «Это не пишущая машинка».
Отправка сигналов
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Все сигналы в конечном счете доставляются ядром, но исходят из различных источников, как показано на рисунке. Для отправки сигналов из командной строки используется команда kill, обычно таким образом:
$ kill -SIGINT 11434 11559
11434 и 11559 – идентификаторы процессов-приемников.
Отправить сигналы можно только тем процессам, владельцем которых являетесь вы (если вы не root). Вместо имени сигнала допускается его номер; можно также не набирать SIG в начале имени, поэтому три следующих команды эквивалентны:
$ kill -SIGKILL 11434 $ kill -KILL 11434 $ kill -9 11434
Команда называется «kill», потому что во многих случаях ее результатом становится завершение процесса; но это не самое лучшее имя. «Throw» [выбросить] или «send-signal» [послать сигнал] было бы лучше.
Неудобство kill в том, что нужно знать числовой идентификатор процесса. Команда pkill позволяет задать процессы, которым отправляются сигналы, другими способами. Вот три примера:
$ pkill -SIGHUP syslogd $ pkill -SIGTERM -U fred $ pkill -SIGKILL -P 13579
Первый сигнал отправляется всем процессам, выполняющим syslogd. Второй – всем процессам, владельцем которых является fred, а третий – всем процессам, чей родительский PID 13579.
В оболочке есть встроенная команда trap, упрощающая обработку сигнала в сценариях без необходимости сочинять нудный код на C, как делают записные хакеры. Trap принимает два аргумента: команду (или набор команд) и имя сигнала, и обеспечивает выполнение указанных команд при получении сигнала с заданным номером. Попробуйте создать такой скрипт:
trap ‘echo I got a SIGHUP signal’ SIGHUP trap ‘echo Terminating on SIGTERM; exit 1’ SIGTERM while true do sleep 1; date done
Сделайте его исполняемым и запустите в фоне – так вы легко сможете узнать идентификатор процесса:
$ chmod u+x trapdemo $ ./trapdemo & [1] 18729
Скрипт печатает дату и ждет секунду. Поэкспериментируйте с командой kill, отправляя сигналы различных типов с другого терминала. При отправке SIGHUP скрипт сообщит, что получил сигнал, и продолжит работу. В ответ на SIGTERM он выведет сообщение и завершится. При получении любого другого сигнала выполнится действие по умолчанию.
Советы программистам
Программистам также могут быть интересны различные сигналы, но им нужно разбираться в сигналах слегка по иным причинам. Наверное, главное, что нужно знать программисту о сигналах – как заставить программу игнорировать их. Причин такого поведения может быть множество, но надо уметь обращаться с сигналами не только затем, чтобы просто наделить процессы возможностью выживания: сигналы обеспечивают обратную связь от системы.
Вот еще несколько вещей, для которых программисту могут пригодиться сигналы:
- обработать SIGHUP для перечитывания конфигурационных файлов, обычно для демонов;
- обработать SIGTERM, чтобы убрать за собой и корректно завершить работу;
- обработать SIGCHLD, чтобы асинхронно собрать результаты завершения дочерних процессов;
- обработать SIGALRM для реализации таймаута при блокирующих операциях;
- обработать SIGUSR1 (или другой сигнал по вашему выбору), чтобы сообщить текущий статус процесса;
- использовать сигнал, чтобы динамически включать и выключать отладочные сообщения.
Если вы серьезно заинтересовались сигналами с точки зрения программиста, раздобудьте книгу Ричарда Стивенса «UNIX. Профессиональное программирование» и погрузитесь в ее десятую главу.
Сигналы и статус выхода
Если программа запускается из командной строки и завершается сигналом, в оболочке появится сообщение об этом. Например, при завершении программы сигналом SIGTERM оболочка выводит сообщение “Terminated”. Для программы, убитой сигналом SIGKILL, выводится сообщение “Killed”, а для программы, совершившей самоубийство попыткой обратиться по неверному адресу памяти – сообщение “Segmentation fault”. По статусу выхода оболочка знает, что процесс завершен сигналом.
У программы, завершившейся нормально, статус выхода равен нулю. Программа, которая (добровольно) завершается с ошибкой, возвратит статус выхода в диапазоне 1–127. А программа, завершенная сигналом, возвратит статус выхода, равный 128 плюс номер соответствующего сигнала. Мы можем увидеть это, запустив заведомо кривую программу на C и просмотрев статус выхода путем вывода значения специальной переменной оболочки $?
$ ./forcesignal Segmentation fault $ echo $? 139
Здесь статус выхода 139 (128+11) сообщает нам о том, что программа завершилась по сигналу 11 (SIGSEGV), что мы преднамеренно и пытались спровоцировать.