Verzeiflung nach FORK

re
Nochmal was zu den Zombies: Wenn man das Child einfach nochmal forken lässt, und dann das Grandchild die Arbeit machen lässt, während sich das Child sofort wieder beendet, und man den Vater-Prozess auf das Child warten lässt via wait(), was kein Problem ist, da Child ja sofort zurückkehrt, dann entstehen erst gar keine Zombies :slight_smile:

Nachteil ist, dass man 2x forkt, was natürlich ineffizient ist (aber dafür sehr portabel).

:slight_smile:


man könnte auch den filedescriptor mit dup2 in stdout kopieren und dann einfach mit printf senden… oder nich ?

oder ist die methode mit dem fdopen eleganter ? weiss nich wie gern des gesehn wird wenn stdout überschrieben wird…


das is eigentlich egal du musst halt nach printf nen fflush machen damit der buffer auch auf stdout geschrieben wird

und falls printf <0 dann haste halt nen fehler oder die verbindung wurde vom client unterbrochen

ich habs auch mit printf gemacht so sieht der code schön sauber aus

was deine 2 forks angeht

If a child as requested by  pid  has  already
       exited  by  the  time  of the call (a so-called "zombie" process), the function returns immediately.  Any system resources used by the child are
       freed.

würdest du dann nicht einen prozess erstellen der darauf wartet dass sein child endet aber dann selbst zu nem zombie wird? so hab ich das jedenfalls verstanden

da stellt sich mir die frage ob man nen beendeten prozess nicht nochmals verwenden könnte @SOS team: geht das?


Da ist es doch schöner der Buffer z.B. mit setvbuf (stdout, NULL, _IONBF, 0) zu entfernen.


If  the  argument  buf  is  NULL,  only the mode is affected; a new buffer will be allocated on the next read or write operation.  The
       setvbuf function may only be used after opening a stream and before any other operations have been performed on it.

ka ob ich das hier richtig verstanden hab aber ich dachte immer das die stdio streams je nach system eine betriebssystem bedingte größe haben
aber wenn ich den auszug aus der manpage dort lese würde das ja heissen
dass die wieder und wieder neuen speicher allokieren und das kann ja wohl nicht ernsthaft ne implementierung sein die man sich wünscht schliesslich will man sich seinen speicher nicht auf diese weise fragmentieren

weiss vllt jemand mehr darüber ob die stdio streams feste größe haben oder nicht?


äh…nee :slight_smile:
Dadurch, dass man 2 mal forkt, und sozusagen die erste Generation sich gleich wieder umbringt, passiert folgendes:
Der Vaterprozess muss nicht auf wait() warten, da der Kindprozess ja sofort stirbt.
Dadurch wird der Enkelprozess zum Waisen, und stellt sein SIGCHLD an init zu, was ihn dann sofort aufräumt, sobald er sich beendet.
Also keine Zombies mehr :slight_smile:


@lord of code:
Buffer & OS: Ja, haben sie, aber die kanns du änderen. Sogar auf shell-ebene, wenn ich mich recht erinner. Ansonsten hab ich eine etwas andere docu:


Leute ich hab ein Problem:
wenn ich daheim mein timed mit

gcc -ansi -pedantic -D_POSIX_SOURCE -D_XOPEN_SOURCE=500 -Wall -Werror -c current_time.c
gcc -ansi -pedantic -D_POSIX_SOURCE -D_XOPEN_SOURCE=500 -Wall -Werror -c timed.c
gcc -ansi -pedantic -D_POSIX_SOURCE -D_XOPEN_SOURCE=500 -Wall -Werror -o timed.o current_time.o

kompiliere dann passt alles und mein prog laeuft wie es soll.

Wenn ich das aber so in der uni mache (per ssh)

gcc -ansi -pedantic -D_POSIX_SOURCE -D_XOPEN_SOURCE=500 -Wall -Werror -c current_time.c
gcc -ansi -pedantic -D_POSIX_SOURCE -D_XOPEN_SOURCE=500 -Wall -Werror -c timed.c

funktioniert aber

gcc -ansi -pedantic -D_POSIX_SOURCE -D_XOPEN_SOURCE=500 -Wall -Werror -o timed.o current_time.o

liefert folgene nachricht

timed.o: In function `main':
timed.o(.text+0xac): undefined reference to `__xnet_socket'
timed.o(.text+0xf0): undefined reference to `__xnet_bind'
timed.o(.text+0x128): undefined reference to `listen'
timed.o(.text+0x178): undefined reference to `accept'
collect2: ld returned 1 exit status

meine includes sind

#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

Uebersehe ich etwas weils schon so spaet/frueh ist oder was ist los ?
Es ist ja alles eingebunden, ich weis auch net :-/

Danke im voraus.

Peace


hatte ma sonen ähnlichen fehler wenn als ich die sys/ includes ned ganz oben hatte


Auf welchem Rechner hast du das gemacht? Ich hab versucht, den timed auf einer Sun zu kompillieren und genau die Fehlermeldungen bekommen…


Die Zeile ist dein Fehler … du bindest current_time.o zu timed.o … das ist glaub ich nicht so ganz das was du willst … :slight_smile:
Füge einfach ein timed hinter -o ein dann sollte es funktionieren … also

gcc -ansi -pedantic -D_POSIX_SOURCE -D_XOPEN_SOURCE=500 -Wall -Werror -o timed timed.o current_time.o

Aufgabestellung
In der Aufgabenstellung steht nichts von send und recv. Bei TCP-Sockets sind diese
Funktionen IMHO ueberfluessig bzw. ungeschickt. Ansonsten duerft Ihr natuerlich
auch send und recv in der Aufgabe verwenden, genauso wie fdopen oder dup. Wenn Ihr
etwas explizit nicht verwenden duerft bzw. sollt, dann wird dieses in den Tafel-Uebungen bzw.
auf dem Aufgabenblatt so auch gesagt.

Tip: Ich wuerde einfach fdopen verwenden und mit printf bzw. puts arbeiten.

Das Abfragen von errno ist wirklich schlechter Stil. Bei readdir hat
euer Uebungleiter/in das bestimmt auch so gesagt.(bzw. haette sollen) Es gilt nie errno Abfragen sondern immer den Rueckgabewert!!
Ausnahme: Es gibt keinen sinnvollen Rueckgabewert, oder keinen anderen sinnvollen Mechanimus. Bsp. readdir.

send und recv haben einen sinnvollen Rueckgabewert.

Haettest Du diesen verwendet, dann haettest Du auch keinen Frust gehabt. – QED

P.S. Was hat das eigentlich mit fork zu tun?


Um das Programm auf einer Sun zu kompilieren muss man noch zwei Liabaries mit angeben beim Kompilieren. Dazu muss man die Optionen ‘-lsocket -lnsl’ mit angeben.

gcc -ansi -pedantic  -D_POSIX_SOURCE -D_XOPEN_SOURCE=500 -Wall -Werror -lsocket -lnsl -o timed timed.o current_time.o

Dann funktioniert timed auch unter SunOS.
Das einzige was ich nicht ferstehe ist, das in der ‘struct sockaddr_in’, die ich dem accept() uebergebe keine IP-Adresse, des Clients drinsteht.


@Wawi: Wie hier schon mehrmals erwähnt hat sich das Problem gelöst. Ich dachte das send irgendwie nicht blicken würde, wenn der Socket geschlossen wird. Immerhin wurde keine Fehlermeldung gegeben(da der Prozess zu deem zeitpunkt schon tot war). Und meine Lösung taugt dann doch ganz gut das Child kontrolliert zu beenden. Dass ich -1 von send zu dem Zeitpunkt (nicht mehr) abgefangen hab ist eine andere Sache.
Ach ja und mit fork hat das zu tun, da es im Childprozessärger macht.


@mirq, hi ne das wars nicht da hab ich gestern einfach das „timed“ vergessen mit reinzutun.

@lix, das ging schon besser

ich hatte mich mit wwwcip.informatik.uni-erlangen.de per ssh, verbunden lag das eventuel daran?
Welche Rechner sind da ueberhaupt alle auf SunOS ?

peace


uname sagt dir das Betriebssystem auf einen Rechner


faui02 [src]> uname
SunOS

na da wird einem alles klar, danke fuer den tip :slight_smile: @mikey.

peace