Учебники

Perl — Управление процессами

Вы можете использовать Perl различными способами для создания новых процессов в соответствии с вашими требованиями. В этом руководстве будет перечислено несколько важных и наиболее часто используемых методов создания и управления процессами Perl.

  • Вы можете использовать специальные переменные $$ или $ PROCESS_ID, чтобы получить текущий идентификатор процесса.

  • Каждый процесс, созданный с помощью любого из упомянутых методов, поддерживает свою собственную виртуальную среду с переменной % ENV .

  • Функция exit () всегда выходит только из дочернего процесса, который выполняет эту функцию, и основной процесс в целом не завершится, если не завершены все запущенные дочерние процессы.

  • Все открытые дескрипторы дублируются в дочерних процессах, поэтому закрытие любых дескрипторов в одном процессе не влияет на другие.

Вы можете использовать специальные переменные $$ или $ PROCESS_ID, чтобы получить текущий идентификатор процесса.

Каждый процесс, созданный с помощью любого из упомянутых методов, поддерживает свою собственную виртуальную среду с переменной % ENV .

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

Все открытые дескрипторы дублируются в дочерних процессах, поэтому закрытие любых дескрипторов в одном процессе не влияет на другие.

Оператор Backstick

Этот самый простой способ выполнения любой команды Unix — с помощью оператора backstick. Вы просто помещаете свою команду внутри оператора backstick, что приведет к ее выполнению и вернет ее результат, который можно сохранить следующим образом:

#!/usr/bin/perl

@files = `ls -l`;

foreach $file (@files) {
   print $file;
}

1;

Когда приведенный выше код выполняется, он перечисляет все файлы и каталоги, доступные в текущем каталоге —

drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy

Функция system ()

Вы также можете использовать функцию system () для выполнения любой команды Unix, чей вывод будет отправлен на вывод сценария perl. По умолчанию это экран, т. Е. STDOUT, но вы можете перенаправить его в любой файл, используя оператор перенаправления> —

#!/usr/bin/perl

system( "ls -l")

1;

Когда приведенный выше код выполняется, он перечисляет все файлы и каталоги, доступные в текущем каталоге —

drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy

Будьте осторожны, когда ваша команда содержит переменные среды оболочки, такие как $ PATH или $ HOME. Попробуйте следующие три сценария —

#!/usr/bin/perl

$PATH = "I am Perl Variable";

system('echo $PATH');  # Treats $PATH as shell variable
system("echo $PATH");  # Treats $PATH as Perl variable
system("echo \$PATH"); # Escaping $ works.

1;

Когда приведенный выше код выполняется, он дает следующий результат в зависимости от того, что установлено в переменной оболочки $ PATH.

/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
I am Perl Variable
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin

Функция fork ()

Perl предоставляет функцию fork (), которая соответствует системному вызову Unix с тем же именем. На большинстве Unix-подобных платформ, где доступен системный вызов fork (), Perl fork () просто вызывает его. На некоторых платформах, таких как Windows, где системный вызов fork () недоступен, Perl может быть построен для эмуляции fork () на уровне интерпретатора.

Функция fork () используется для клонирования текущего процесса. Этот вызов создает новый процесс, выполняющий ту же программу в той же точке. Он возвращает дочерний pid родительскому процессу, 0 — дочернему процессу или undef, если ответвление не выполнено.

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

Live Demo

#!/usr/bin/perl

if(!defined($pid = fork())) {
   # fork returned undef, so unsuccessful
   die "Cannot fork a child: $!";
} elsif ($pid == 0) {
   print "Printed by child process\n";
   exec("date") || die "can't exec date: $!";
  
} else {
   # fork returned 0 nor undef
   # so this branch is parent
   print "Printed by parent process\n";
   $ret = waitpid($pid, 0);
   print "Completed process id: $ret\n";

}

1;

Когда приведенный выше код выполняется, он дает следующий результат —

Printed by parent process
Printed by child process
Tue Sep 17 15:41:08 CDT 2013
Completed process id: 17777

Wait () и waitpid () могут быть переданы как идентификатор псевдопроцесса, возвращаемый fork (). Эти вызовы будут должным образом ожидать завершения псевдопроцесса и возвращать его статус. Если вы разветвляетесь, не дожидаясь своих детей, используя функцию waitpid () , вы будете накапливать зомби. В системах Unix вы можете избежать этого, установив для $ SIG {CHLD} значение «IGNORE» следующим образом:

Live Demo

#!/usr/bin/perl

local $SIG{CHLD} = "IGNORE";
 
if(!defined($pid = fork())) {
   # fork returned undef, so unsuccessful
   die "Cannot fork a child: $!";
} elsif ($pid == 0) {
   print "Printed by child process\n";
   exec("date") || die "can't exec date: $!";
  
} else {
   # fork returned 0 nor undef
   # so this branch is parent
   print "Printed by parent process\n";
   $ret = waitpid($pid, 0);
   print "Completed process id: $ret\n";

}

1;

Когда приведенный выше код выполняется, он дает следующий результат —

Printed by parent process
Printed by child process
Tue Sep 17 15:44:07 CDT 2013
Completed process id: -1

Функция kill ()

Функция Perl kill (‘KILL’, (Process List)) может быть использована для завершения псевдопроцесса путем передачи ему идентификатора, возвращаемого fork ().

Обратите внимание, что использование kill (‘KILL’, (Process List)) в псевдопроцессе () может обычно вызывать утечки памяти, поскольку поток, реализующий псевдопроцесс, не получает возможности очистить свои ресурсы.

Вы можете использовать функцию kill () для отправки любого другого сигнала целевым процессам, например, следующая команда отправит SIGINT идентификаторам процессов 104 и 102 —