Unix / Linux - сигналы и ловушки
В этой главе мы подробно обсудим сигналы и ловушки в Unix.
Сигналы - это программные прерывания, отправляемые программе, чтобы указать, что произошло важное событие. События могут варьироваться от запросов пользователя до ошибок незаконного доступа к памяти. Некоторые сигналы, такие как сигнал прерывания, указывают на то, что пользователь попросил программу сделать что-то, что не входит в обычный поток управления.
В следующей таблице перечислены общие сигналы, с которыми вы можете столкнуться и которые хотите использовать в своих программах.
Имя сигнала | Номер сигнала | Описание |
---|---|---|
SIGHUP | 1 | Обнаружено зависание на управляющем терминале или смерть управляющего процесса |
SIGINT | 2 | Выдается, если пользователь отправляет сигнал прерывания (Ctrl + C) |
SIGQUIT | 3 | Выдается, если пользователь отправляет сигнал выхода (Ctrl + D) |
SIGFPE | 8 | Выдается при попытке выполнения недопустимой математической операции |
СИГКИЛЛ | 9 | Если процесс получает этот сигнал, он должен немедленно завершить работу и не будет выполнять никаких операций очистки. |
SIGALRM | 14 | Сигнал будильника (используется для таймеров) |
SIGTERM | 15 | Сигнал завершения программы (по умолчанию отправляется командой kill) |
Список сигналов
Существует простой способ перечислить все сигналы, поддерживаемые вашей системой. Просто выдайтеkill -l команда, и она отобразит все поддерживаемые сигналы -
$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT
17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU
25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN
35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4
39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6
59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
Фактический список сигналов варьируется между Solaris, HP-UX и Linux.
Действия по умолчанию
С каждым сигналом связано действие по умолчанию. Действие по умолчанию для сигнала - это действие, которое сценарий или программа выполняет при получении сигнала.
Некоторые из возможных действий по умолчанию:
Завершите процесс.
Игнорируйте сигнал.
Дамп ядра. Это создает файл с именемcore содержащий образ памяти процесса, когда он получил сигнал.
Остановите процесс.
Продолжить остановленный процесс.
Отправка сигналов
Есть несколько методов передачи сигналов программе или сценарию. Один из наиболее распространенных - пользователь набираетCONTROL-C или INTERRUPT key пока выполняется сценарий.
Когда вы нажимаете Ctrl+C ключ, а SIGINT отправляется в сценарий и в соответствии с определенным действием по умолчанию сценарий завершается.
Другой распространенный метод доставки сигналов - использование kill command, синтаксис которого следующий -
$ kill -signal pid
Вот signal это либо номер, либо название сигнала, который нужно доставить и pidэто идентификатор процесса, которому должен быть отправлен сигнал. Например -
$ kill -1 1001
Приведенная выше команда отправляет сигнал HUP или отбоя программе, которая работает с process ID 1001. Чтобы отправить сигнал уничтожения тому же процессу, используйте следующую команду -
$ kill -9 1001
Это убивает процесс, работающий с process ID 1001.
Сигналы захвата
Когда вы нажимаете Ctrl + C или клавишу Break на вашем терминале во время выполнения программы оболочки, обычно эта программа немедленно завершается, и ваша командная строка возвращается. Это не всегда может быть желательно. Например, в конечном итоге вы можете оставить кучу временных файлов, которые не удастся очистить.
Перехватить эти сигналы довольно просто, и команда trap имеет следующий синтаксис:
$ trap commands signals
Здесь команда может быть любой допустимой командой Unix или даже определяемой пользователем функцией, а сигнал может быть списком любого количества сигналов, которые вы хотите перехватить.
Есть два распространенных использования ловушки в сценариях оболочки:
- Очистить временные файлы
- Игнорировать сигналы
Очистка временных файлов
В качестве примера команды trap ниже показано, как вы можете удалить некоторые файлы и затем выйти, если кто-то попытается прервать программу с терминала:
$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2
С того момента в программе оболочки, где выполняется эта ловушка, два файла work1$$ и dataout$$ будет автоматически удален, если программа получит сигнал номер 2.
Следовательно, если пользователь прерывает выполнение программы после выполнения этой ловушки, вы можете быть уверены, что эти два файла будут очищены. Вexit команда, которая следует за rm необходимо, потому что без него выполнение в программе продолжалось бы с той точки, на которой оно остановилось при получении сигнала.
Сигнал номер 1 генерируется для hangup. Либо кто-то намеренно кладет трубку, либо линия случайно отключается.
Вы можете изменить предыдущую ловушку, чтобы также удалить два указанных файла в этом случае, добавив сигнал номер 1 в список сигналов -
$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2
Теперь эти файлы будут удалены , если линия получает повесила трубку или , если Ctrl + C ключ получает нажат.
Команды, указанные для перехвата, должны быть заключены в кавычки, если они содержат более одной команды. Также обратите внимание, что оболочка сканирует командную строку во время выполнения команды trap, а также при получении одного из перечисленных сигналов.
Таким образом, в предыдущем примере значение WORKDIR и $$будет заменен во время выполнения команды trap. Если вы хотите, чтобы эта замена происходила в момент получения сигнала 1 или 2, вы можете поместить команды в одинарные кавычки -
$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2
Игнорирование сигналов
Если команда, указанная для ловушки, имеет значение null, указанный сигнал будет проигнорирован при получении. Например, команда -
$ trap '' 2
Это указывает, что сигнал прерывания следует игнорировать. Вы можете игнорировать определенные сигналы при выполнении операции, которую вы не хотите прерывать. Вы можете указать несколько сигналов, которые следует игнорировать, следующим образом:
$ trap '' 1 2 3 15
Обратите внимание, что первый аргумент должен быть указан для игнорирования сигнала и не эквивалентен написанию следующего, которое имеет отдельное собственное значение:
$ trap 2
Если вы игнорируете сигнал, все подоболочки также игнорируют этот сигнал. Однако, если вы укажете действие, которое должно быть выполнено при получении сигнала, все подоболочки по-прежнему будут выполнять действие по умолчанию при получении этого сигнала.
Сброс ловушек
После того, как вы изменили действие по умолчанию, выполняемое при получении сигнала, вы можете снова изменить его с помощью ловушки, если просто опустите первый аргумент; так что -
$ trap 1 2
Это сбрасывает действие, выполняемое при получении сигналов 1 или 2, обратно к значениям по умолчанию.