Язык программирования Perl

Параллельное выполнение процессов


Для организации параллельного выполнения процессов в Perl используется функция fork ("разветвить"). В результате ее работы создается копия выполняющегося процесса, которая тоже запускается на выполнение. Для этого в операционных системах семейства Unix происходит обращение к системному вызову fork. В других операционных системах работа функции fork() организуется исполняющей системой Perl. Функция fork() в родительском процессе возвращает PID дочернего процесса, число 0 - в дочернем процессе и неопределенное значение при невозможности запустить параллельный процесс. Это значение проверяется в программе, чтобы организовать выполнение различных действий в процессе-предке и процессе-потомке. Как это делается, показано на следующем схематичном примере (где оба процесса в цикле выводят числа, но с разными задержками):

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

По сообщениям, выводимым при выполнении этого примера, видно, что родительский и порожденный процессы выполняются параллельно. Для того чтобы организовать в родительском процессе ожидание завершения дочернего процесса, применяется функция waitpid(), которой передается PID процесса-потомка (а также, возможно, дополнительные параметры). По выдаваемым сообщениям сравните два варианта выполнения приведенной выше программы - без ожидания завершения дочернего процесса и с ожиданием завершения процесса-потомка (для этого нужно раскомментарить вызов функции waitpid):


Без ожидания потомка С ожиданием потомка по waitpid() ---------------------------- -------------------------------- Начался потомок PID -1024 Начался потомок PID -1908 Потомок PID -1024 работает 1 Потомок PID -1908 работает 1 Начался предок PID 1504 Начался предок PID 1876 Предок PID 1504 работает 1 Предок PID 1876 работает 1 Предок PID 1504 работает 2 Предок PID 1876 работает 2 Потомок PID -1024 работает 2 Потомок PID -1908 работает 2 Предок PID 1504 работает 3 Предок PID 1876 работает 3 Закончился предок PID 1504 Предок PID 1876 ждет завершения -1908 Потомок PID -1024 работает 3 Потомок PID -1908 работает 3 Закончился потомок PID -1024 Закончился потомок PID -1908 Закончился предок PID 1876

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


Содержание раздела