Читаем Язык программирования Perl полностью

Примером реальной программы, выполняющейся в бесконечном цикле, может служить любой сервер, ожидающий запросов от клиентских программ и перечитывающий свой конфигурационный файл после получения определенного сигнала (обычно HUP или USR1). Если необходимо временно игнорировать какой-то сигнал, то соответствующему элементу хэша %SIG присваивается строка 'IGNORE'. Восстановить стандартную обработку сигнала можно, присвоив соответствующему элементу %SIG строку 'DEFAULT'.

Процесс может посылать сигналы самому себе, например, для отслеживания окончания запланированного периода времени (для обработки тайм-аута). В приведенном примере длительная операция прерывается по истечении указанного промежутка времени:

# устанавливаем обработчик сигнала ALRM (будильник) $SIG{ALRM} = sub { die "Timeout"; }; # анонимная подпрограмма $timeout = 3600; # определяем величину тайм-аута (сек.) eval { # блок обработки возможной ошибки alarm($timeout); # устанавливаем время отправки сигнала # некая длительная операция: print "Работаю в поте лица...\n" while (1); alarm(0); # нормальное завершение операции }; # в специальной переменной $@ - сообщение об ошибке if ($@ =~ /Timeout/) { # проверяем причину ошибки print "Аварийный выход по истечении времени!"; }

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

my $parent = $$; # PID родительского процесса my $pid = fork(); # 'разветвить' текущий процесс # fork вернет PID потомка в процессе-предке и 0 в потомке die "fork не отработал: $!" unless defined $pid; if ($pid) { # ---------- родительский процесс ---------- print "Начался предок PID $$\n"; for (1..3) { print "Предок PID $$ работает $_\n"; print "Предок PID $$ отправил сигнал\n"; kill HUP, $pid; sleep 2; # 'заснуть' на 2 секунды } print "Закончился предок (PID $$)\n"; } unless ($pid) { # ---------- дочерний процесс ---------- my $counter = 0; # счетчик полученных сигналов $SIG{HUP} = sub { ### обработчик сигнала ### $counter++; print "\tПотомок получил $counter-й сигнал!\n"; }; ### конец обработчика сигнала ### print "\tНачался потомок PID $$ предка $parent\n"; for (1..7) { print "\tПотомок PID $$ работает $_\n"; sleep 1; # 'заснуть' на 1 секунду } print "\tЗакончился потомок PID $$\n"; }

Поведение этих процессов во время выполнения программы можно проследить по выводимым ими сообщениям:

Перейти на страницу:

Похожие книги