Thread View: pl.comp.lang.perl
13 messages
13 total messages
Started by Paweł
Thu, 03 Dec 2009 18:25
wątki
Author: Paweł
Date: Thu, 03 Dec 2009 18:25
Date: Thu, 03 Dec 2009 18:25
52 lines
2009 bytes
2009 bytes
Witam !
W przykładach dotyczących wątków można znaleźć zwykle coś takiego:
$SIG{'CHLD'}=sub { while(waitpid(-1,WNOHANG)>0){} };
defined (my $child=fork()) or die "Błąd wywołania fork():$!";
if ($child==0)
{....
exit 0;}
Interesuje mnie pierwsza lina.
W opisie podają, ze wykonuję sie ona po zakończeniu procesu dziecka.
Nie bardzo mogę zrozumieć w jakim celu.
Jeśli proces się zakończy to zwalniane są zasoby i nie widzę sensu aby
coś jeszcze robić. Jednak jeśli ta linia wykonuje się przed startem
procesu dziecka to jej wywołanie jest dla mnie logiczne. Zapobiegnie ew.
tworzeniu się kolejnych wątków. Czy ktoś może wyjaśnić jak to jest w
rzeczywistości ?
Załóżmy, że program główny składa się z jednej pętli okresowo
wywoływanej. Chcę w tej pętli utworzyć nowy proces. Jednak tylko w
sytuacji gdy poprzedni się zakończył. Czy można zrobić to w ten sposób:
my $t=0;
while (1)
{
...
if ($t==0)
{
defined (my $child=fork()) or die "Błąd wywołania fork():$!";
if ($child==0)
{
$t=1;
...
...
$t=0;
exit 0;}
}
{
Paweł
Re: wątki
Author: Stachu 'Dozzie' K.
Date: Thu, 03 Dec 2009 19:04
Date: Thu, 03 Dec 2009 19:04
46 lines
2275 bytes
2275 bytes
On 03.12.2009, Paweł wrote:
> Witam !
>
>
> W przykładach dotyczących wątków można znaleźć zwykle coś takiego:
>
> $SIG{'CHLD'}=sub { while(waitpid(-1,WNOHANG)>0){} };
>
> defined (my $child=fork()) or die "Błąd wywołania fork():$!";
> if ($child==0)
> {....
> exit 0;}
^
Mógłbyś ten fragment kodu jakoś sformatować? Na przykład kończyć nawiasy
klamrowe w przewidywalnych miejscach? Bo później się bardzo źle czyta
dłuższy kod.
> Interesuje mnie pierwsza lina.
> W opisie podają, ze wykonuję sie ona po zakończeniu procesu dziecka.
> Nie bardzo mogę zrozumieć w jakim celu.
> Jeśli proces się zakończy to zwalniane są zasoby i nie widzę sensu aby
> coś jeszcze robić.
Doczyta o procesach zombie, to będzie wiedział że jeszcze nie wszystko
jest zwalniane.
> Jednak jeśli ta linia wykonuje się przed startem
> procesu dziecka to jej wywołanie jest dla mnie logiczne.
Wykonuje się gdy rodzic zostaje poinformowany o zakończeniu potomka.
Inna sprawa że tu SIGCHLD powinien zostać zignorowany, skoro rodzic
i tak olewa tę informację (waitpid
> Zapobiegnie ew.
> tworzeniu się kolejnych wątków.
Nie widzę o co ci chodzi z tworzeniem kolejnych wątków, ale to pewnie
przez to że wiem jak działają procesy w uniksach.
> Czy ktoś może wyjaśnić jak to jest w
> rzeczywistości ?
google://linux+programmers+guide
--
Stanislaw Klekot
Re: wątki
Author: Paweł
Date: Thu, 03 Dec 2009 19:49
Date: Thu, 03 Dec 2009 19:49
14 lines
1579 bytes
1579 bytes
> > Nie widzę o co ci chodzi z tworzeniem kolejnych wątków, ale to pewnie > przez to że wiem jak działają procesy w uniksach. > Napisałem kiedyś podpierając się różnymi przykładami jeden (tylko jeden) skrypt w Perlu. Co pewien czas wymaga on dodania nowych funkcji ale spełnia swoje do dziś dość ważne zadanie. W ten sposób zostałem zostałem "specjalistą" w dziedzinie Perla. Proszę więc o wybaczenie jeśli używam niepoprawnych określeń. Moja rzeczywista wiedza na temat tego języka jest w zasadzie znikoma. Paweł
Re: wątki
Author: Tomasz "rocku" K.
Date: Thu, 03 Dec 2009 21:02
Date: Thu, 03 Dec 2009 21:02
49 lines
1905 bytes
1905 bytes
Paweł wrote:
> Załóżmy, że program główny składa się z jednej pętli okresowo
> wywoływanej. Chcę w tej pętli utworzyć nowy proces. Jednak tylko w
> sytuacji gdy poprzedni się zakończył. Czy można zrobić to w ten sposób:
>
>
> my $t=0;
> while (1)
> {
> ...
>
> if ($t==0)
> {
> defined (my $child=fork()) or die "Błąd wywołania fork():$!";
> if ($child==0)
> {
> $t=1;
> ...
>
> ...
> $t=0;
> exit 0;}
> }
>
> {
Nie można, ponieważ w momencie wywołania fork() tworzony jest drugi
proces (dziecko), który posiada własną kopię zmiennej $t. Po jego
wywołaniu zmienna $t w procesie rodzica wciąż będzie mieć wartość 0.
Jednym rozwiązaniem byłoby sprawdzenie w procesie rodzica czy dziecko
jeszcze istnieje, np. tak:
$SIG{CHLD} = 'IGNORE';
my $child;
while(1) {
unless (defined $child && kill 0, $child) {
defined($child = fork()) or die $!;
if (! $child) {
print "I'm the child\n";
exit 0;
}
}
sleep 1;
}
--
Pozdrawiam,
Tomasz "rocku" K.
Re: wątki
Author: Paweł
Date: Thu, 03 Dec 2009 22:03
Date: Thu, 03 Dec 2009 22:03
43 lines
2935 bytes
2935 bytes
> Jednym rozwiązaniem byłoby sprawdzenie w procesie rodzica czy dziecko
> jeszcze istnieje, np. tak:
>
> $SIG{CHLD} = 'IGNORE';
> my $child;
> while(1) {
> unless (defined $child && kill 0, $child) {
> defined($child = fork()) or die $!;
> if (! $child) {
> print "I'm the child\n";
> exit 0;
> }
> }
> sleep 1;
> }
>
W moim przypadku chyba nie można zrobić tego w ten sposób.
Skrypt jest uruchomiony jako demon i odbiera dane przez sieć z kilku
źródeł. Dla każdego źródła wykonywane są identyczne operacje ale dla
każdego niezależnie.
Proces rodzica zapisuje odebrane dane na lokalnym dysku we właściwych
dla danego źródła plikach. To musi działać stale, bez żadnych przerw.
Dodatkowo muszę przesyłać skompletowane w procesie rodzica dane na inne
serwery (różne dla różnych źródeł danych). Nie ma gwarancji, że te
zdalne serwery będą działały wystarczająco szybko aby udało się w czasie
rzeczywistym wszystko do nich wysłać. Jednak dane na te serwery wysyła
się w małych porcjach. Każda taka porcja stanowi oddzielną całość. Nic
wielkiego się nie stanie jeśli jakaś paczka nie zostanie przesłana.
W celu wysłania takiej paczki danych do danego serwera chcę utworzyć
proces dziecka. Przy czym kolejną porcję danych będę pomijał jeśli
poprzednia nie zdołała się przesłać. Czyli czym wolniejszy ten zdalny
serwer to więcej danych będzie tracone.
W celu zrealizowanie opisanej funkcjonalności przed wywołaniem procesu
dziecka muszę sprawdzić czy poprzedni proces się zakończył.
Kłopot polega jednak na tym, że mogę mieć uruchomionych kilka różnych
procesów dziecka dla różnych źródeł danych (dla rożnych serwerów). Musze
więc sprawdzić czy zakończył się dany proces dziecka. Jak to zrobić ?
Paweł
Re: wątki
Author: Marcin Gryszkalis
Date: Fri, 04 Dec 2009 06:54
Date: Fri, 04 Dec 2009 06:54
21 lines
1595 bytes
1595 bytes
Paweł wrote: > Musze > więc sprawdzić czy zakończył się dany proces dziecka. Jak to zrobić ? Tworząc tablicę pid-ów dzieci i sprawdzając funkcją waitpid z WNOHANG. Z drugiej strony może spróbuj poszukać w CPAN-ie - jest sporo modułów, które ukrywają te wszystkie wnętrzności i działają całkiem sensownie (jedyny problem, że jeśli coś nie będzie działać do końca poprawnie to nie rozumiejąc jak to wszystko pracuje nie będziesz mógł poprawić). np. Parallel::ForkManager, subs::parallel, Parallel::ForkControl, Parallel::Jobs i pewnie jeszcze parę innych pozdrawiam -- Marcin Gryszkalis, PGP 0x9F183FA3 jabber jid:mg@fork.pl, gg:2532994 http://the.fork.pl
Re: wątki
Author: Tomasz "rocku" K.
Date: Fri, 04 Dec 2009 09:32
Date: Fri, 04 Dec 2009 09:32
13 lines
1450 bytes
1450 bytes
Paweł wrote: > W celu zrealizowanie opisanej funkcjonalności przed wywołaniem procesu > dziecka muszę sprawdzić czy poprzedni proces się zakończył. > Kłopot polega jednak na tym, że mogę mieć uruchomionych kilka różnych > procesów dziecka dla różnych źródeł danych (dla rożnych serwerów). Musze > więc sprawdzić czy zakończył się dany proces dziecka. Jak to zrobić ? fork() zwraca pid procesu dziecka. Możesz w prosty sposób zmapować serwery docelowe na odpowiadające im procesy dziecka, np. w hashu. -- Pozdrawiam, Tomasz "rocku" K.
Re: wątki
Author: Paweł
Date: Fri, 04 Dec 2009 22:00
Date: Fri, 04 Dec 2009 22:00
14 lines
1625 bytes
1625 bytes
> fork() zwraca pid procesu dziecka. Możesz w prosty sposób zmapować
> serwery docelowe na odpowiadające im procesy dziecka, np. w hashu.
>
Nie wiem jednak jak poprawnie sprawdzić czy dany proces jeszcze się
wykonuje.
Wykombinowałem sobie taki kod:
$SIG{'CHLD'}=sub {my $pid = wait; print $pid."\n" };
Wyświetla on numer procesu dziecka, który się zakończył
Czy ten mechanizm mogę wykorzystać do usuwania elementów z wyżej
wymienionego hasha ?
Paweł
Re: wątki
Author: Andrzej Adam Filip
Date: Fri, 04 Dec 2009 22:37
Date: Fri, 04 Dec 2009 22:37
37 lines
2556 bytes
2556 bytes
Paweł <pawel.neo@neostrada.pl> pisze:
>> fork() zwraca pid procesu dziecka. Możesz w prosty sposób zmapować
>> serwery docelowe na odpowiadające im procesy dziecka, np. w hashu.
>
> Nie wiem jednak jak poprawnie sprawdzić czy dany proces jeszcze się
> wykonuje.
> Wykombinowałem sobie taki kod:
> $SIG{'CHLD'}=sub {my $pid = wait; print $pid."\n" };
> Wyświetla on numer procesu dziecka, który się zakończył
> Czy ten mechanizm mogę wykorzystać do usuwania elementów z wyżej
> wymienionego hasha ?
Zasadniczo tak o ile pamiętasz że:
a) możesz dostać jeden SIGCHLD na kilka zakończeń procesów-potomków
wiec lepiej stosować to co sugerują w "man perlipc"
use POSIX ":sys_wait_h";
sub REAPER {
my $child;
while (($child = waitpid(-1,WNOHANG)) > 0) {
$Kid_Status{$child} = $?;
}
$SIG{CHLD} = \&REAPER; # still loathe SysV
}
$SIG{CHLD} = \&REAPER;
b) W "złośliwym" przypadku potomek może się zakończyć zanim rodzic go
zdąży wpisać do hasha :-)
A tak z ciekawości: dlaczego używasz procesów a nie wątków (threads)?
--
Andrzej Adam Filip : anfi@onet.eu : Andrzej.Filip@gmail.com
Zawsze jestem gotów się uczyć, chociaż nie zawsze chcę, żeby mnie uczono.
-- Churchill, Winston (1874-1965)
[ http://groups.google.pl/groups?selm=2s5u0s3krz-9C4@lonnie.brudna.chmurka.net ]
Re: wątki
Author: Paweł
Date: Sat, 05 Dec 2009 08:23
Date: Sat, 05 Dec 2009 08:23
29 lines
2025 bytes
2025 bytes
> a) możesz dostać jeden SIGCHLD na kilka zakończeń procesów-potomków
> wiec lepiej stosować to co sugerują w "man perlipc"
>
> use POSIX ":sys_wait_h";
> sub REAPER {
> my $child;
> while (($child = waitpid(-1,WNOHANG)) > 0) {
> $Kid_Status{$child} = $?;
> }
> $SIG{CHLD} = \&REAPER; # still loathe SysV
> }
> $SIG{CHLD} = \&REAPER;
Sprawdziłem, że podany przykład działa. Jednak mam problem z jego
zrozumieniem.
Co robi:
$SIG{CHLD} = \&REAPER;
> A tak z ciekawości: dlaczego używasz procesów a nie wątków (threads)?
>
Domyślnie obsługa wątków w Perlu na serwerze jest wyłączona. Zapewne
można ją jakoś dodać. Boję się, że jak zacznę coś zmieniać na serwerze
to wszystko przestanie działać.
Paweł
Re: wątki
Author: Adam Osuchowski
Date: Sat, 05 Dec 2009 08:38
Date: Sat, 05 Dec 2009 08:38
15 lines
1666 bytes
1666 bytes
Paweł wrote:
> Sprawdziłem, że podany przykład działa. Jednak mam problem z jego
> zrozumieniem.
> Co robi:
> $SIG{CHLD} = \&REAPER;
Ustanawia funkcję REAPER jako obsługującą sygnał SIGCHLD (sygnał
wysyłany do procesu-rodzica, gdy proces-potomek zostanie zatrzymany lub
zakończony).
Ponieważ poruszasz się na styku programowania systemowego i programowania
w Perlu, poczytaj jakiś poradnik do programowania systemowego w uniksie,
a następnie manuale perlowe (w tym wypadku opis jest w perlvar).
Zdecydowanie pomoże Ci to w zrozumieniu co, jak i dlaczego się dzieje,
co z czego wynika i pozwoli objąć problem z szerszej perspektywy.
Re: wątki
Author: Paweł
Date: Sat, 05 Dec 2009 18:36
Date: Sat, 05 Dec 2009 18:36
13 lines
1628 bytes
1628 bytes
>> while (($child = waitpid(-1,WNOHANG)) > 0) {
>> $Kid_Status{$child} = $?;
>> }
Zrobiłem wszystko co chciałem opierając się na podanym przykładzie.
Wygląda, że skrypt działa tak jak trzeba.
Mam jednak jeszcze jedno pytanie. Czy może się zdarzyć aby "$?" wyżej
podanym kodzie zawierało wartość inną niż zero ?
Paweł
Re: wątki
Author: Maciej Zielenkieiwcz
Date: Sat, 05 Dec 2009 19:05
Date: Sat, 05 Dec 2009 19:05
14 lines
1663 bytes
1663 bytes
On 2009-12-05 18:36, Paweł <pawel.neo@neostrada.pl> wrote:
>
>>> while (($child = waitpid(-1,WNOHANG)) > 0) {
>>> $Kid_Status{$child} = $?;
>>> }
>
> Zrobiłem wszystko co chciałem opierając się na podanym przykładzie.
> Wygląda, że skrypt działa tak jak trzeba.
>
> Mam jednak jeszcze jedno pytanie. Czy może się zdarzyć aby "$?" wyżej
> podanym kodzie zawierało wartość inną niż zero ?
Tak, jeżeli proces który się zakończył zakończy się z błędem (zwróci coś
różnego od zera).
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads