Perl - zarządzanie procesami
Możesz używać Perla na różne sposoby, aby tworzyć nowe procesy zgodnie z własnymi wymaganiami. Ten samouczek zawiera listę kilku ważnych i najczęściej używanych metod tworzenia i zarządzania procesami Perla.
Możesz użyć specjalnych zmiennych $$ lub $PROCESS_ID aby uzyskać bieżący identyfikator procesu.
Każdy proces utworzony za pomocą którejkolwiek z wymienionych metod ma swoje własne wirtualne środowisko %ENV zmienna.
Plik exit() function zawsze kończy tylko proces potomny, który wykonuje tę funkcję, a proces główny jako całość nie zakończy działania, chyba że zakończą się wszystkie uruchomione procesy potomne.
Wszystkie otwarte uchwyty są dup () - ed w procesach potomnych, więc zamknięcie któregokolwiek z uchwytów w jednym procesie nie wpływa na pozostałe.
Operator Backstick
Najprostszym sposobem wykonania dowolnego polecenia Uniksa jest użycie operatora backstick. Po prostu umieszczasz swoje polecenie wewnątrz operatora backstick, co spowoduje wykonanie polecenia i zwróci jego wynik, który można zapisać w następujący sposób -
#!/usr/bin/perl
@files = `ls -l`;
foreach $file (@files) { print $file;
}
1;
Kiedy powyższy kod jest wykonywany, wyświetla listę wszystkich plików i katalogów dostępnych w bieżącym katalogu -
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
Funkcja system ()
Możesz także użyć system()funkcja do wykonania dowolnego polecenia systemu Unix, którego dane wyjściowe trafią do wyjścia skryptu Perla. Domyślnie jest to ekran, czyli STDOUT, ale możesz przekierować go do dowolnego pliku za pomocą operatora przekierowania> -
#!/usr/bin/perl
system( "ls -l")
1;
Kiedy powyższy kod jest wykonywany, wyświetla listę wszystkich plików i katalogów dostępnych w bieżącym katalogu -
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
Uważaj, gdy twoje polecenie zawiera zmienne środowiskowe powłoki, takie jak $PATH or $DOM. Wypróbuj trzy scenariusze -
#!/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;
Wykonanie powyższego kodu daje następujący wynik w zależności od tego, co jest ustawione w zmiennej powłoki $ 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
Funkcja fork ()
Perl udostępnia fork()funkcja, która odpowiada wywołaniu systemowemu Unix o tej samej nazwie. Na większości platform podobnych do Uniksa, na których funkcja systemowa fork () jest dostępna, funkcja fork () w Perlu po prostu ją wywołuje. Na niektórych platformach, takich jak Windows, gdzie wywołanie systemowe fork () nie jest dostępne, Perl można zbudować tak, aby emulował fork () na poziomie interpretera.
Funkcja fork () służy do klonowania bieżącego procesu. To wywołanie tworzy nowy proces z tym samym programem w tym samym punkcie. Zwraca pid potomny do procesu nadrzędnego, 0 do procesu potomnego lub undef, jeśli rozwidlenie się nie powiedzie.
Możesz użyć exec() funkcja w procesie, aby uruchomić żądany plik wykonywalny, który zostanie wykonany w oddzielnym obszarze procesu, a funkcja exec () będzie czekać na jego zakończenie przed zakończeniem z tym samym kodem zakończenia, co ten proces.
#!/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;
Wykonanie powyższego kodu daje następujący wynik -
Printed by parent process
Printed by child process
Tue Sep 17 15:41:08 CDT 2013
Completed process id: 17777
Plik wait() i waitpid()może być przekazany jako identyfikator pseudoprocesu zwracany przez fork (). Te wywołania będą poprawnie czekać na zakończenie pseudoprocesu i zwrócą jego stan. Jeśli widelec, nigdy nie czekając, aż twoje dzieci będą używaćwaitpid()funkcja, będziesz gromadzić zombie. W systemach uniksowych można tego uniknąć ustawiając $ SIG {CHLD} na "IGNORE" w następujący sposób -
#!/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;
Wykonanie powyższego kodu daje następujący wynik -
Printed by parent process
Printed by child process
Tue Sep 17 15:44:07 CDT 2013
Completed process id: -1
Funkcja kill ()
Perl kill('KILL', (Process List)) funkcja może być użyta do zakończenia pseudoprocesu poprzez przekazanie mu ID zwróconego przez fork ().
Zauważ, że użycie funkcji kill ('KILL', (Lista procesów)) w pseudo-procesie () może zazwyczaj powodować wycieki pamięci, ponieważ wątek implementujący pseudoproces nie ma szansy na wyczyszczenie swoich zasobów.
Możesz użyć kill() funkcja do wysyłania dowolnego innego sygnału do procesów docelowych, na przykład następująca wyśle SIGINT do ID procesu 104 i 102 -
#!/usr/bin/perl
kill('INT', 104, 102);
1;