Moduł Proc::Fork

Uniwersytet Gdański - Instytut Matematyki - Zakład Informatyki - Strona domowa

Obsługa modułu Proc::Fork

Co to jest

Proces - to jedno z najbardziej podstawowych pojęć w informatyce. Jest to po prostu egzemplarz wykonywanego programu. Należy odróżnić jednak proces od wątku - każdy proces posiada własną przestrzeń adresową, natomiast wątki posiadają wspólną sekcję danych. Każdemu procesowi przydzielone zostają zasoby, takie jak procesor, pamięć, dostęp do urządzeń wejścia-wyjścia, pliki. Każdy proces posiada tzw. "rodzica". W ten sposób tworzy się swego rodzaju drzewo procesów. Proces może mieć również procesy potomne. Za zarządzanie procesami odpowiada jądro systemu operacyjnego.

Proc::Fork to moduł autorstwa Aristotle Pagaltzis'a. Moduł, który przedstawię pozwala nam na podział programu na osobne procesy.

Download

Instalacja w systemie UNIX'owym

Po rozpakowaniu modułu wydajemy polecenie

perl Makefile.PL make make install

Sprawdzamy, czy został on pomyślnie zainstalowany, pisząc jednolinijkowca perl -e 'use Proc::Fork' Pomyślne wykonanie programu (żadnych komunikatów) daje nadzieję, że moduł został zainstalowany poprawnie i będzie działał. Jeżeli wszystko poszło zgodnie z planem to możemy już korzystać z możliwości naszego nowego modułu.

Opis

Używanie modułu jest naprawdę intuicyjne. Możemy pisać programy korzystające z procesów, używając bloków, które w prosty sposób odpowiadają za wykonanie kodu w odpowiednim procesie. Kod dla procesu rodzicielskiego, potomnego, uchwytu wznowienia oraz uchwytu dla błędów jest zgrupowany w bloki procesu. Bloki te mogą pojawić się w dowolnej kolejności, lecz nie możemy umieszczać żadnych danych pomiędzy nimi. Obowiązkowy jest również przecinek na końcu bloku. Nie trzeba umieszczać wszystkich czterech bloków. Jeżeli zostanie pominięty blok rodzicielski lub potomny, to odpowiedni proces zacznie wykonywanie po ostatnim bloku, możemy to przedstawić tak:

# Proces potomny child { coś do zrobienia }; # Proces rodzicielski rozpocznie wykonywanie od tego momentu coś do zrobienia

Interfejs

child
Ta funkcja wykonuje przekazany do niej kod, jeżeli będzie to proces potomny child { ... }
parent
Ta funkcja wykonuje przekazany do niej kod, jeżeli będzie to proces rodzicielski. Umieszcza PID procesu potomnego. parent { ... }
retry
Ta funkcja wykonuje przekazany do niej kod, jeżeli wystąpił błąd lub proces zwrócił undef. Jeżeli kod zwróci true, podejmowany jest kolejny proces. Jeżeli ten blok nie jest użyty, nie zostaną podjęte żadne wznowienia i niepowodzenie procesu doprowadzi do błędu bloku do którego się odwołuje proces. retry { ... }
error
Ta funkcja wykonuje przekazany do niej kod, jeżeli wystąpił błąd, proces zwrócił undef i blok wznowienia (retry) zwrócił false. Jeżeli blok błedu nie jest użyty, wszelkie błędy podniosą wyjątek używając die. error { ... }

Eksport

Pakiet ten eksportuje domyślnie następujące symbole

  • child
  • parent
  • retry
  • error

Przykład

Pierwszy program będzie polegał na wypisaniu tekstu na ekran (przekazanego przez proces potomny) przez proces rodzicielski. Kod posiada komentarz, więc powinien być zrozumiały dla każdego.

use strict; use IO::Pipe; use Proc::Fork; #Rura my $p = new IO::Pipe; #Proces rodzicielski parent { print "Jestem w parent\n"; #PID potomnego my $child = shift; #Czytamy z rury $p->reader; #Wypisujemy zawartość jeżeli coś się pojawiło print while ( <$p> ); waitpid $child,0; } #Proces potomny child { print "Jestem w child\n"; #Piszemy do rury $p->writer; print $p "Piszemy "; print $p "Coś\n"; };

Oto co otrzymamy po wykonaniu programu

zad1

Drugi program pokazuje komunikację z wieloma procesami potomnymi. Za każdym razem angażowane są inne procesy potomne.

use strict; use Proc::Fork; use IO::Pipe; my $num_children = 5; #Ilość utworzonych procesów my @children; #Tablica w której przechowujemy połączenia do procesów #Dla każdego procesu jest tworzona rura do komunikacji for my $num ( 1 .. $num_children ) { #Utworzenie rury do połączenia my $pipe = new IO::Pipe; # Proces potomny wypisuje otrzymane dane child { $pipe->reader; my $data; while ( $data = <$pipe> ) { chomp $data; print STDERR "child $num: [$data]\n"; } exit; }; #Proces rodzicielski przechowuje połączenia do każdego procesu w tablicy @children $pipe->writer; push @children, $pipe; } # Wysyłamy dane do losowych procesów for ( 1 .. 20 ) { #Losujemy numer procesu my $num = int rand $num_children; #Połączenie z odpowiednim procesem my $child = $children[$num]; #Wysyłamy komunikat print $child "Cześć to ja.\n"; }

Pierwsze przykładowe wykonanie programu

zad1

Drugie przykładowe wykonanie programu

zad1

Dodatkowe informacje

Za pomocą tego modułu możemy tworzyć bardzo ciekawe programy, począwszy od podziału zadań w programie na poszczególne procesy, do wszelkiego rodzajów 'demonów' i usług sieciowych. Po dodatkowe informacje odsyłam na stronę z dokumenacją modułu.

Autor opracowania

Adrian Sielski

Email: adrian.sielski@gmail.com

Uniwersytet Gdański - Instytut Matematyki - Zakład Informatyki - Strona domowa - Perl - Wyklady
[c] Piotr Arłukowicz, materiały z tej strony udostępnione są na licencji GNU.