Язык программирования Perl
Язык программирования Perl читать книгу онлайн
Курс знакомит с языком программирования Perl, с его принципами, основными возможностями и особенностями в объёме, достаточном, чтобы начать разрабатывать прикладные и системные задачи, включая программирование для сети Интернет.
Курс является достаточно подробным введением в язык программирования Perl. Описывается уникальная культура Perl и особенности, отличающие его от других языков программирования и во многом обусловившие его популярность. Рассматриваются основные средства программирования на языке Perl версии 5.8. Разбираются богатые возможности языка для создания самых разных приложений, а также особый стиль программирования на Perl. Курс ориентирован на студентов, начинающих программистов или разработчиков, применяющих другие языки и желающих писать прикладные или системные программы на Perl.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
print "Это сообщение никогда не напечатается!n";
При запуске этого примера с параметром 'proc_executed.pl' будут выведены такие сообщения:
Выполняется загрузчик: proc_exec.pl, PID:652
Запускается программа: proc_executed.pl
Выполняется программа: proc_executed.pl, PID:1872
Для организации параллельного выполнения процессов в 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 $$ ждет завершения $pidn";
# 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, если все процессы-потомки завершили работу.
В Perl есть несколько способов организации взаимодействия процессов при их параллельном выполнении. Один из них - создать программный канал (pipe), который представляет из себя два файловых манипулятора - приемник (reader) и передатчик (writer) - связанных таким образом, что записанные в передатчик данные могут быть прочитаны из приемника. Программный канал создается с помощью функции pipe(), которой передаются имена двух файловых манипуляторов: приемника и источника. Один из вариантов взаимодействия процессов через программный канал показан в следующем примере:
use IO::Handle; # подключаем стандартный модуль
pipe(READER, WRITER); # создаем программный канал
WRITER->autoflush(1); # включаем авто-очистку буфера
if ($pid = fork()) { # процесс-предок получает PID потомка
close READER; # предок не будет читать из канала
print WRITER "Послано предком (PID $$):n";
for (my $n = 1; $n <= 5; $n++) { # запись в передатчик
print WRITER "$n ";
}
close WRITER; # закрываем канал и
waitpid $pid, 0; # ждем завершения потомка
}
die "fork не отработал: $!" unless defined $pid;
if (!$pid) { # процесс-потомок получает 0
close WRITER; # предок не будет писать в канал
print "Потомок (PID $$) прочитал:n";
while (my $line = <READER>) { # чтение из приемника
print "$line";
}