Глава 14: Управление процессами.
14.4 Использование функции fork
Еще один способ создания нового процесса — клонирование текущего Perl-процесса с помощью UNIX-функции fork. Функция fork делает то же самое, что и системний вызов fork(2): создает клон текущего процесса. Этот клон (он называется порожденным процессом, а оригинал — родительским) использует тот же выполняемый код, те же переменные и даже те же открьггые файлы. Различаются эти два процесса по возвращаемому значенню функции fork: для порожденного процесса оно равно нулю, а для родительского — ненулевое (или undef, если этот системний вызов окажется неудачним). Ненулевое значение, получаемое родительским процессом,— это не что иное как идентификатор порожденного процесса. Ви можете проверить возвращае-мое значение и действовать соответственно:
if (!defined($child_pid = fork()) {
die "cannot fork: $!";
} elsif ($pid) {
# я — родительский процесс
} else {
# я — порожденннй процесс
}
Чтобы максимально эффективно использовать этот клон, нам нужно изучить еще несколько функции, которые весьма похожи на своих UNIX-тезок: это функции wait, exit и ехес.
Самая простая из них — функция ехес. Это почти то же самое, что и функция system, за тем исключением, что вместо запуска нового процесса для выполнения shell-команды Perl заменяет текущий процесс на shell. После успешного выполнения ехес Perl-программа исчезает, поскольку вместо нее выполняется затребованная программа. Например,
ехес "date";
заменяет текущую Perl-программу командой date, направляя результат этой команды на стандартный вывод Perl-программы. После завершення команды date делать больше нечего, потому что Perl-программа давно исчезла.
Все это можно рассматривать и по-другому: функция system похожа на комбинацию функции fork c функцией ехес, например:
# МЕТОД 1... использование system:
system("date");
# МЕТОД 2... использование fork/exec:
unless (fork) {
# fork выдала нуль, поэтому я — порожденный процесс и я выполняю:
exec ("date") ; # порожденный процесс становится командой date
}
Использовать fork и exec таким способом — не совсем правильно, потому что команда date и родительский процесс "пыхтят" одновременно, их результаты могут переметаться и испортить все дело. Как дать родительскому процессу указание подождать, пока не завершится порожденный процесс? Именно это и делает функция wait; она ждет завершення данного (да и любого, если быть точним) порожденного процесса. Функция waitpid более разборчива: она ждет завершення не любого, а определенного порожденного процесса:
if (!defined($kidpid = fork()) {
# fork возвратила undef, т.е. неудача
die "cannot fork: $!";
} elsif ($pid =" 0) {
# fork возвратила О, поэтому данная ветвь — порожденный процесс
exec("date");
# если exec терпит неудачу, перейти к следующему оператору
die "can't exec date: $!";
} else {
# fork возвратила не 0 и не undef,
# поэтому данная ветвь — родительский процесс
waitpid($kidpid, 0);
}
Если все это кажется вам слишком сложным, изучите системные вызовы fork(2) и ехес(2), отыскав материалы о них в каком-нибудь руководстве по ОС UNIX, потому что Perl просто передает вызовы этих функций прямо в системные вызовы UNIX.
Функция exit обеспечивает немедленный выход из текущего Perl-процесса. Она используется для прерывания Perl-программы где-нибудь посередине или — вместе с функцией fork — для выполнения Perl-кода в процессе с последующим выходом. Вот пример удаления нескольких файлов из каталога///?у? в фоновом режиме с помощью порожденного Perl-процесса:
unless (defined ($pid = fork)) {
die "cannot fork: $!";
}
unless ($pid) {
unlink </tmp/badrock.*>; # удалить эти файлы
exit; # порожденный процесс останавливается здесь
}
# родительский процесс продолжается здесь
waitpid($pid, 0); # после уничтожения порожденного процесса нужно все убрать
Без использования функций exit порожденный процесс продолжал бы выполнять Perl-код (со строки "# родительский процесс продолжается здесь") — а как раз этого нам и не нужно.
Функция exit может иметь необязательный параметр, служащий числовим кодом выхода, который воспринимается родительским процессом. По умолчанию выход производится с нулевым кодом, показывающим, что все прошло нормально.
Назад | Вперед
Содержание (общее) | Содержание раздела
Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
|