Forum: PC-Programmierung Unix Prozessprogrammierung


von Andre (Gast)


Lesenswert?

Hallo zusammen

Ich möchte in einem C-Programm unter Unix einen neuen Prozess erzeugen. 
Dieser sollte 20 Sekunde warten, nach Ablauf dieser 20 Sekunden einen 
ICMP-Ping lossenden und falls der Teilnehmer antwortet, dies in eine 
Logfile schrieben.

Das Hauptprogramm soll allerdings nicht warten sondern weiterlaufen. 
Leider blockiert das Hauptsprogramm trotz entsprechender aufrufe.

Auszug:
1
switch(PID = fork())
2
{
3
  case -1:
4
       printf("Error");
5
       break;
6
  case 0:
7
       sleep(20);
8
       .....ping Teilnehmer
9
       break;
10
  default:
11
       waitpid(PID, &status, WNOHANG);
12
       break;
13
}


Ich danke Euch im Voraus für eure Hilfe

von Konrad S. (maybee)


Lesenswert?

Nein, das Hauptprogramm blockiert nicht. Es macht genau das, was du 
programmiert hast und das ist ... na ... genau: waitpid(). Also warten.

von Andre (Gast)


Lesenswert?

Hmm... Ich will einfach nur dafür sorgen, dass keine Zombies im System 
bleiben. Daher das waitpid.

von Konrad S. (maybee)


Lesenswert?

Aus der Linux-manpage von waitpid:
1
POSIX.1-2001 specifies that if the disposition of  SIGCHLD  is  set  to
2
SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)),
3
then children that terminate do not become zombies and a call to wait()
4
or  waitpid()  will  block until all children have terminated, and then
5
fail with errno set to ECHILD.  (The original POSIX standard  left  the
6
behavior  of  setting  SIGCHLD  to SIG_IGN unspecified.  Note that even
7
though the default disposition of SIGCHLD is "ignore", explicitly  set‐
8
ting  the disposition to SIG_IGN results in different treatment of zom‐
9
bie process children.)  Linux 2.6 conforms to this specification.  How‐
10
ever,  Linux  2.4 (and earlier) does not: if a wait() or waitpid() call
11
is made while SIGCHLD is being ignored, the call behaves just as though
12
SIGCHLD were not being ignored, that is, the call blocks until the next
13
child terminates and then returns the process ID  and  status  of  that
14
child.

von Konrad S. (maybee)


Lesenswert?

Oder das, hier die Methode "double fork" (frei nach Stephen A. Rago, 
UNIX System V Network Programming)
1
if ( (pid = fork()) < 0 ) {
2
  exit( 1 );
3
} else if ( pid == 0 ) {
4
  /* child level 1 */
5
  setsid();
6
  sigset( SIGHUP, SIG_IGN );
7
  if ( (pid = fork()) < 0 ) {
8
    exit( 1 );
9
  } else if ( pid != 0 ) {
10
    /* parent */
11
    exit( 0 );
12
  }
13
  /* child level 2 */
14
  ...
15
  exit( 0 );
16
}
17
/* parent */

von Rayray (Gast)


Lesenswert?

Hallo Andre,

statt der waitpid schreibst Du was Dein Hauptprogramm machen soll, 
während der Kindprozess läuft.

Vor dem fork fügst Du folgenden Zeile ein:
1
signal(SIGCHLD,Handler);

Die folgende Funktion kommt vor main
1
void Handler(int n) {
2
   /* Zombies entfernen */
3
   wait3(NULL,WNOHANG,NULL);
4
}

Ein Kind das sich beendet erzeugt ein SIGCHILD-Signal, das üblicherweise 
ignoriert wird. Durch die signal...-Zeile richtest Du ne Handler für 
SIGCHLD ein. Die Funktion Handler wird jedesmal aufgerufen, wenn sich 
ein Kind beendet. So wirst Du die Zombies los und kannst im 
Elternprozess noch was "sinnvolles" machen.

Rayray

von Peter II (Gast)


Lesenswert?

warum überhaupt den krampf mit dem fork()? Wo es noch keine Threads gab 
war es ja ok, aber mittlerweile finde ich den ansatz nicht mehr 
sinnvoll. Man muss in dem Programm jedesmal aufpassen ob man nun child 
oder parrent ist, dateihandel werden auch einfach kopiert dann muss man 
aufpassen das man sie richtig schliest. Auch der Austausch von Daten 
zwischen den Programmen geht nicht so einfach. Der speicherverbauch 
dürfte auch mehr sein, wenn 2 Programme laufen.

Ich würde einfach einen Thread starten und dort die hauptarbeit machen. 
Oder gibt es noch eine (PC)-Platform wo es keine pthread lib gibt?

von Konrad S. (maybee)


Lesenswert?

Wie immer: Kommt darauf an, was wichtig ist und welche Kenntnisse sind 
vorhanden.
Bei Threads ist die Performanz höher und der Ressourcenverbrauch 
geringer. Bei fork() gibt es mehr funktionierende Code-Beispiele. 
"Schöne" Fehler kann man mit beiden Verfahren programmieren.

Evtl. geht die einfachste Lösung so:
1
 system( "sleep 20; ping -c 1 localhost >/dev/null 2>&1 && echo OK >logfile" );
(Der ping ist hier für Linux formuliert.)

von Rolf M. (rmagnus)


Lesenswert?

Konrad S. schrieb:
> Wie immer: Kommt darauf an, was wichtig ist und welche Kenntnisse sind
> vorhanden.
> Bei Threads ist die Performanz höher und der Ressourcenverbrauch
> geringer.

Das ist zumindest unter Linux nicht zwingend der Fall.

> Evtl. geht die einfachste Lösung so:
> system( "sleep 20; ping -c 1 localhost >/dev/null 2>&1 && echo OK
> logfile" );
> (Der ping ist hier für Linux formuliert.)

Genau sowas hätte ich auch vorgeschlagen. Mit threads zu hantieren und 
dann in C zu warten und mit Sockets zu basteln, nur um ein Ping 
abzusetzen, finde ich viel zu umständlich. Mit einem kleinen Skript hat 
viel weniger Aufwand.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.