Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.
Aufgabe 6 - piper
Hallo zusammen!
Habe eine Frage zu Aufgabe 6 - genauer gesagt zum Modul sbuf.
Die Funktion
SBUF* sbufCreate(int maxNumberOfSems)
soll - soweit ich das verstanden habe - bei jedem Aufruf einen neuen Puffer für Semaphore anlegen.
Das heißt, ich brauche irgendwo in meinem sbuf-Modul eine SBUF **buffer-Variable, um all diese einzelnen Puffer speicher zu können, oder?
Aber wie sieht diese SBUF-Struktur denn aus?
Habe Probleme bei der
int sbufAddSem(SBUF* cl, SEM* sem)
-Funktion:
sbuf.c:44:5: error: invalid use of undefined type ‘struct SBUF’
if(buffer[i][j] == NULL){
^
sbuf.c:44:17: error: dereferencing pointer to incomplete type
if(buffer[i][j] == NULL){
^
sbuf.c:45:6: error: invalid use of undefined type ‘struct SBUF’
buffer[i][j] = sem;
^
sbuf.c:45:15: error: dereferencing pointer to incomplete type
buffer[i][j] = sem;
.
Ich habe mir halt gedacht, das ist wie ein 2-dimensionales Array und ich schreibe in den richtigen Puffer an der ersten freien Stelle den übergebenen Semaphor rein.
Doch irgendwie klappt da gar nichts
Kann mir jemand ein wenig auf die Sprünge helfen?
Vielen Dank!
Im Header wird der Typ [m]SBUF[/m] als incomplete Type deklariert:
typedef struct SBUF SBUF;
Der Compiler weiß nur, dass [m]SBUF[/m] ein Alias für [m]struct SBUF[/m] ist (Deshalb kann man im Header [m]SBUF[/m]-Pointer verwenden, aber keine Strukturelemente). In der Datei sbuf.c musst du den Typ [m]struct SBUF[/m] selbst deklarieren, damit du auf die einzelnen Elemente der Datenstruktur zugreifen kannst.
Hi zusammen,
ich möchte ausprobieren, ob mein Programm (noch in den Kinderschuhen) schon richtig in eine pipe schreibt.
Ich habe die Pipe als Argument übergeben, prüfe im Schreibthread, ob es eine Pipe ist und wollte mit
fputs(“Test”, pipe) in meine Pipe schreiben,. Das wird auch ausgeführt, aber wenn ich dann in der Shell
cat meinePipe aufrufe, dann tut sich nichts. Der Befehl blockiert dann und ich muss mit STRG+C abbrechen.
Woran könnte das liegen?
Ich habe auch schon versucht in der Shell einzugeben:
mkfifo meinePipe
echo hallo > meinePipe
da blockiert’s dann auch. was mache ich falsch?
Operationen auf einer pipe blockieren so lange, bis sie zum lesen und schreiben geöffnet wurde. Du musst das [m]echo[/m] als Hintergrundprozess ausführen, da es blockiert, bis [m]cat[/m] die pipe zum lesen öffnet:
mkfifo pipe
echo hello > pipe &
cat pipe
ah cool, das funktioniert schon mal, aber wie mache ich das dann in meinem Code? Ich öffne ja die Pipe und schließe sie wieder. Wenn ich dann in der Shell cat aufrufen möchte, funktioniert das ja dann wieder nicht, oder müsste ich dann erst wieder reinschreiben, damit ich lesen kann?
Ich nochmal
Mittlerweile hänge ich denk ich mal hauptsächlich an den Semaphoren. Anscheinend habe ich da was falsch verstanden,
denn mein Plan war folgender:
In der Main-Methode erstelle ich mir erst mal ein Semaphor mit dem Wert 1 (nur ein Thread darf arbeiten, wenn P aufgerufen wird),
dann blockiere ich noch vor dem Erstellen der Threads das Semaphor. In der Methode, die den Threads übergeben wird, dachte ich
dann, dass ich die Threads nach dem Öffnen der Pipe auch gegen einen P-Aufruf desselben Semaphors laufen lasse. Dann könnte
der Main-Thread über fgets eine Zeile einlesen und dann die restlichen Threads aufwecken und die würden das dann in die Pipe schreiben.
Soweit der Plan. Leider ist es so, dass der P-Aufruf in der Methode, die den Threads übergeben wird, gar nichts bewirkt. Die laufen einfach
drüber und führen die Methode zu Ende aus.
Kann mir jemand sagen, wo mein Denkfehler liegt?
Aus genau diesem Grund darf man die Pipe nicht wieder schließen. Die Schreib-Threads müssen die Pipe am Anfang öffnen und dann die ganze Zeit offen halten.
Dazu kann man ohne Code kaum etwas sagen… Am besten fragst du das in der Rechnerübung.
Soll die Meldung “[piper] There are currently x clients” (siehe Referenz-Implementierung) auch auf stderr ausgegeben werden oder auf stdout?
Kannst du auch schnell selbst testen.
Wenn du ein Programm in der Konsole aufrufst, kannst du mit >datei stdout in datei umleiten, mit 2> entsptrechend stderr.
Außerdem gibt’s auf Unixsystem noch das nulldevice /dev/null. Alles was dorthingeschrieben wird, wird sofort verworfen.
Startest du piper mit >/dev/null, wird alles was auf stdout ausgegeben wird, sofort verworfen. Taucht deine gesuchte Meldung dann nicht mehr auf, wird sie wohl auf stdout ausgegeben.
Ausgeben
Volschaf: Da hast du zwar Recht, aber ich glaube die Frage war, ob man es wie in der Musterimplementierung auch auf stderr ausgeben soll.
Mir ist auch schon aufgefallen, dass gelegentlich Ausgabetexte der Musterimplementierung auf stderr ausgegeben haben.
Auf Nachfrage bei meinem Tutor meinte er aber, das hätte eher den Grund, dass man die Ausgaben dann einfach besser rausfiltern kann.
Normal und schön ist es, wenn man so Ausgaben, die zum Programm normal dazugehören (Dazu würde ich die Meldung, wieviel Pipes gerade geöffnet sind zählen) einfach auf stdout ausgeben, Fehlermeldungen auf stderr. Damit hatte ich bislang noch keine Probleme bekommen.
Mit Grüßen, Alicen