Schrift
[thread]5892[/thread]

fork problem: mal wieder..

Leser: 3


<< |< 1 2 >| >> 11 Einträge, 2 Seiten
steinwolf
 2003-11-08 17:52
#70644 #70644
User since
2003-08-04
367 Artikel
BenutzerIn
[default_avatar]
Hai,
erstmal ein Codeschnipsel:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!perl -w

use strict;

my $pid;
my $flag = 0;

if(!defined($pid = fork)) {
die "Cannot fork: $!";
} elsif($pid == 0) {
while($flag == 0) {
print "SLEEP FOR A SEC.\n";
}

} else {
sleep(1);
$flag = 1;
}


Das Problem ist, dass das Skript nach einer Sekunde nicht abbricht, sondern als Endlosschleife weiterläuft. Warum das?
Ich kann das Flag doch sowohl im Child- als auch im Parentprozess beeinflussen!?

mfg stein
"Did you know? You can use your old motor oil to fertilize your lawn." - Blinkster - Professionelles EDV Forum
esskar
 2003-11-08 18:11
#70645 #70645
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
nein....
die variablen werden bei fork quasi gedoppelt...
das kind hat nachdem fork den gleichen stand wie der papa...
danach arbeiten sie aber getrennt voneinander
steinwolf
 2003-11-08 18:31
#70646 #70646
User since
2003-08-04
367 Artikel
BenutzerIn
[default_avatar]
Und wie kann ich dann zwischen den Prozessen quasi "kommunizieren"? Bestes Beispiel wäre eine Fortschrittsanzeige. Womöglich über Pipes? Irgendwelche andere Vorschläge?? Sowas wird doch bestimmt oft gebraucht.

mfg stein
"Did you know? You can use your old motor oil to fertilize your lawn." - Blinkster - Professionelles EDV Forum
esskar
 2003-11-08 22:46
#70647 #70647
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    sub pipe_to_fork ($) {
       my $parent = shift;
       pipe(my $child, $parent) or die;
       my $pid = fork();
       die "fork() failed: $!" unless defined $pid;
       if ($pid) {
           close $child;
       }
       else {
           close $parent;
           open(STDIN, "<&=" . fileno($child)) or die;
       }
       $pid;
   }

   if (pipe_to_fork('FOO')) {
       # parent
       print FOO "pipe_to_fork\n";
       close FOO;
   }
   else {
       # child
       while (<STDIN>) { print; }
       close STDIN;
       exit(0);
   }
\n\n

<!--EDIT|esskar|1068423759-->
betterworld
 2003-11-09 03:01
#70648 #70648
User since
2003-08-21
2614 Artikel
ModeratorIn

user image
Wenn nicht wirklich viel Informationen rueber kommen sollen (wie es bei einer Fortschrittsanzeige der Fall ist), eignen sich eventuell auch Signale. Beispiel:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
use strict;
use warnings;

# Hier wird definiert, was getan werden soll, wenn
# ein USR1-Signal kommt
$SIG{"USR1"} = sub { print "Wie die Zeit vergeht...\n"; };

# Hier wird definiert, was getan werden soll, wenn
# ein Kindprozess sich beendet (also wenn ein CHLD-Signal
# kommt)
$SIG{"CHLD"} = sub { print "Und vorbei!\n"; exit(0); };

my $parent_pid = $$;
defined(my $child_pid = fork()) or die "fork problem";

if(! $child_pid){
# Child
for(1..3){
kill "USR1", $parent_pid; # ein USR1-Signal schicken
sleep 1;
}
exit(0);
}

# Parent
# wir muessen dafuer sorgen, dass der Prozess am Leben bleibt.
# Sonst koennen wir nicht mehr auf die Signale reagieren.
sleep while 1;


P.S.: Hier muss man mit der Synchronisation aufpassen. Wenn man die fork-Anweisung und die beiden Zeilen, in denen die Signal-Handler vergeben werden, vertauscht, *kann* es passieren, dass das USR1-Signal verschickt wird, bevor der entsprechende Signalhandler aufgesetzt wurde. Das wird zur Folge haben, dass der Parent-Prozess fruehzeitig getoetet wird (Standardreaktion fuer USR1).\n\n

<!--EDIT|betterworld|1068342662-->
steinwolf
 2003-11-09 11:10
#70649 #70649
User since
2003-08-04
367 Artikel
BenutzerIn
[default_avatar]
Hm..ist wohl ein bisschen komplizierte. Gibts eigtl. ein Buch, das dieses Thema forking explizit in Perl behandelt?

@esskar: So ist's wahrscheinlich besser, dann bekommt man bei aktivem strict auch keine Fehlermeldung mehr:
pipe (my $child, $parent) or die;
;-)
@betterworld:
kann ich anstatt USR1 jeden beliebigen String zur Kommunikation einsetzen?
Danke für die Hilfe.
mfg stein
"Did you know? You can use your old motor oil to fertilize your lawn." - Blinkster - Professionelles EDV Forum
betterworld
 2003-11-09 15:15
#70650 #70650
User since
2003-08-21
2614 Artikel
ModeratorIn

user image
[quote=steinwolf,09.11.2003, 10:10]Hm..ist wohl ein bisschen komplizierte. Gibts eigtl. ein Buch, das dieses Thema forking explizit in Perl behandelt?
[/quote]
"man perlipc" jedenfalls sagt alles ueber Kommunikation zwischen Prozessen.

Quote
kann ich anstatt USR1 jeden beliebigen String zur Kommunikation einsetzen?

Nicht jeden, aber so ziemlich jeden, der von "kill -l" (Shellbefehl/Linux) aufgelistet wird. Manche haben aber besondere Bedeutungen und sollten nicht verwendet werden (SIGKILL z.B. laesst sich gar nicht abfangen. SIGINT sollte man auch nicht abfangen, weil man sonst das Programm nicht mehr ueber Strg-C abbrechen kann). Mehr dazu in "man 7 signal".
Beliebige Strings lassen sich nicht uebertragen. Dazu muss man dann Pipes verwenden. Es lassen sich also nicht wirklich Daten uebertragen, sondern nur Zeitpunkte. Deswegen schrieb ich auch "Wenn nicht wirklich viel Information..."\n\n

<!--EDIT|betterworld|1068384737-->
esskar
 2003-11-10 02:23
#70651 #70651
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
[quote=steinwolf,09.11.2003, 10:10]@esskar: So ist's wahrscheinlich besser, dann bekommt man bei aktivem strict auch keine Fehlermeldung mehr:
pipe (my $child, $parent) or die;
;-)[/quote]
danke... verbessert!
Benutzer
 2008-06-18 13:39
#111181 #111181
User since
2008-06-18
7 Artikel
BenutzerIn
[default_avatar]
Moin,

ich bin auf der Suche nach einer Fortschrittsanzeige für ein Terminal. Es soll einfach nur angezeigt werden ob der Prozess noch am rödeln ist.
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
sub Fortschrittsanzeige{
$|=1;
print "\b\|";
sleep(1);
print "\b/";
sleep(1);
print "\b-";
sleep(1);
print "\b\\";
sleep(1);
print "\b ";
return;
}


Kriege ich das irgendwie mit 'fork()'; 'wait()' und 'pipe()' hin. Oder muss ich mit 'kill()' hart durchgreifen?

Danke und Grüsse
renee
 2008-06-18 14:06
#111184 #111184
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Schau Dir mal diesen Thread an: http://board.perl-community.de/thread/6181/startWi...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
<< |< 1 2 >| >> 11 Einträge, 2 Seiten



View all threads created 2003-11-08 17:52.