П О Р Т А Л                            
С Е Т Е В Ы Х                          
П Р О Е К Т О В                        
  
Поиск по сайту:
                                                 
Главная

О проекте

Web-мастеру
     HTML & JavaScript
     SSI
     Perl
     PHP
     XML & XSLT
     Unix Shell

MySQL

Безопасность

Хостинг

Другое








Самое читаемое:

Учебник PHP - "Для Чайника".
Просмотров 3511 раз(а).

Иллюстрированный самоучитель по созданию сайтов.
Просмотров 6115 раз(а).

Учебник HTML.
Просмотров 3268 раз(а).

Руководство по PHP5.
Просмотров 5491 раз(а).

Хостинг через призму DNS.
Просмотров 4129 раз(а).

Подборка текстов стандартных документов.
Просмотров 55769 раз(а).

Учебник PHP - Самоучитель
Просмотров 3084 раз(а).

Документация на MySQL (учебник & справочное руководство)
Просмотров 5610 раз(а).

Внешние атаки...
Просмотров 3834 раз(а).

Учебник PHP.
Просмотров 2821 раз(а).

SSI в примерах.
Просмотров 37458 раз(а).



 
 
| Добавить в избранное | Сделать стартовой | Помощь





Глава 14: Управление процессами.
14.6 Передача и прием сигналов

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

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

Все это аналогично тому, что делается и в других языках программирования, но сейчас излагаемый материал приобретет специфический Perl-оттенок. Когда Perl-процесс перехватывает сигнал, асинхронне и автоматически вызывается указанная вами подпрограмма, моментально прерывая выполнявшийся до нее код. Когда эта подпрограмма завершается, выполнение прерванного кода возобновляется, как будто ничего не случилось (за исключением появлення результатов действий, выполненных этой подпрограммой,— если она вообще что-нибудь делала).

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

* Попытка выполнения действий более сложных, чем вышеописанные, вероятнее всего, запутает ситуацию; большинство внутренних механизмов Perl "не любят", когда их вызывают одновременно в основной программе и из подпрограммы. Ваши системные библиотеки тоже этого "не любят".

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

Имена сигналов определяются на man-странице signal(2), а также, как правило, в подключаемом С-файле /usr/include/sys/signal.h. Эти имена обычно начинаются с букв sig, например sigint, sigquit и sigkill. Чтобы обьявить подпрограмму my_sigint_catcher() обработчиком сигнала sigint, мы должны установить соответствующее значение в специальном хеше %sig. В этом хеше в качестве значения ключа int (это sigint без sig) следует указать имя подпрограммы, которая будет перехватывать сигнал sigint:

$SIG{'INT'} = 'my_sigint_catcher';

Но нам понадобится также определение этой подпрограммы. Вот пример простого определения:

sub my_sigint_catcher {
  $saw_sigint = 1; # установить флаг
}

Данный перехватчик сигналов устанавливает глобальную переменную и сразу же возвращает управление. Выполнение программы продолжается с той позиции, в которой оно было прервано. Обычно сначала обнуляется флаг $saw_sigint, соответствующая подпрограмма определяется как перехватчик сигнала sigint, а затем следует код основной программы, например:

$saw_sigint = 0; # очистить флаг
$SIG{'INT'} = 'my_sigint_catcher'; # зарегистрировать перехватчик

foreach (@huge_array) {
  # что-нибудь сделать
  # еще что-нибудь сделать
  # и еще что-нибудь

  if ($saw_sigint) { # прерывание нужно?
    # здесь "очистка" 
    last;
  }
}
$SIG('INT'} = 'DEFAULT'; # восстановить действие по умолчанию

Особенность использования сигнала в данном фрагменте программы состоит том, что значение флага проверяется в важнейших точках процесса вычисления и используется для преждевременного выхода из цикла; при этом выполняется и необходимая "очистка". Обратите внимание на последний оператор в приведенном выше коде: установка действия в значение default восстанавливает действие конкретного сигнала по умолчанию (следующий сигнал sigint немедленно прервет выполнение программы). Еще одно полезное специальное значение вроде этого — ignore, т.е. "игнорировать сигнал" (если действие по умолчанию — не игнорировать сигнал, как у sigint). Для сигнала можно установить действие ignore, если не нужно выполнять никакой "очистки" и вы не хотите преждевременно завершать выполнение основной программы.

Один из способов генерирования сигнала sigint — заставить пользователя нажать на клавиатуре терминала соответствующие прерыванию клавиши (например, [Ctrl+C]). Процесс тоже может генерировать сигнал sigint, используя для этого функцию kill. Данная функция получает номер или имя сигнала и посылает соответствующий сигнал в процессы (обозначенные идентификаторами) согласно списку, указанному после сигнала. Следовательно, для передачи сигнала из программы необходимо определить идентификаторы процессов-получателей. (Идентификаторы процессов возвращаются некоторыми функциями, например функцией fork, и при открытии программы как дескриптора файла функцией open). Предположим, вы хотите послать сигнал 2 (известный также как sigint) в процессы 234 и 237. Это делается очень просто:

kill(2,234,237); # послать SIGINT в 234 и 237

kill ('INT', 234, 237); # то же самое

Более подробно вопросы обработки сигналов описаны в главе 6 книги Programming Perl и на man-странице perlipc(l).

Назад | Вперед
Содержание (общее) | Содержание раздела



Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
 





Copyright © 2005-2016 Project.Net.Ru