Aufgabe 8

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 8
WIe sollen wir eigentlich das einfügen und auslesen im Ringpuffer realisieren?
per “keystroke”? und wenn die Sem blockiert einfach keinen weiter keystroke zulassen?
höh?


Man liest ja irgendwie die Zeichen ein (z.B. mit getchar).
wenn man ein Zeichen hat, schreibt man’s in den Puffer.
Wenn nix mehr in den Puffer reinpasst blockiert die P-Operation
und der Prozess macht eh’ kein getchar mehr.

Der Aerger mit dem getchar (oder auch read) ist natuerlich, dass
die Zeilenpufferung des Treibers immer nur nach einem return
die Zeichen weitergibt.

Damit kann man derzeit nur returns einzeln eingeben, sonst immer mind.
ein Zeichen + return.
Dieses Problem loesen wir dann in A9 wenn wir den Treober auf Einzelzeicheneingabe umstellen. In A8 muss man damit leben.


okay, danke.

der erzeuger soll ja, wenn ich das richtgi verstanden habe, terminieren sobald der ringpuffer leer ist. und die eingabe geschieht durch eine schleife mit eben dieser abbruchbedinung. sollen wir 2 “pausen” in die schleife bauen damit man zeit hat den verbraucher etwas zu fressen? weil ansonsten kommt man schlecht aus der schleie raus, weil sobald man etwas geschreiben hat ist der puffer ja schonmal nicht leer und die überprüfung am ende der schleife ist negativ bzgl eines abbruchs. Ausser: (und das wäre die einzige möglichkeit) man sagt dem verbraucher das er alles fressen soll, dann is der puffer leer (die sem operation blockiert) und das system ist solagne blockiert bis man eine taste drückt und der erzeuger was schreibt. dann braucht man glück… wenn der scheduler jetzt den verbraucher ranlässt bevor die abbruchbedinung gestestet wird kann er den puffer leeren und somit den erzeuger und das ganze system terminieren…

okay. ich glaube ich mach erstmal 2 “breakpoints” weil das hört sich doch erstmal total [quote=prof. stoyan]
verrückt
[/quote]
an ;)))

edit:
und gleich noch eine verständnissfrage hinterher:
die kritischen operationen beim ringpuffer sind ja das lesen und schreiben.
aber wie kann man die operationen denn sichern? in der vl gabs da ja diese P und V operationen, aber die hab ich jetzt erhlich gesagt überhauptnicht in meinem semaphoren verständniss. gibts dir hier auch?
oder muss ich VOR dem schreiben den semaphorenwert erhöhen und NACH dem eintragen den entsprehcenden lese semaphorenwert senken??
das zerstört jetzt aber irgendwie den atomaren charakter den die operationen brauchen.

öööhh… und überhaupt kommt mir das falsch vor.

müssen wir eigentlich irgendwelche compileoptionen beachten??


verwirr doch die anderen nicht so, eem :slight_smile:

Terminieren sobald der puffer leer ist? Wie sinnvoll ist das? Vielleicht liest du einfach nochmal die Aufgabenstellung und bemerkst dann, dass der Erzeuger bevor er sich beendet (also wenn man z.B. Strg-C drückt) noch ein paar Dinge zu erledigen hat (siehe Aufgabestellung). Der Satz heißt nicht, dass er sich beenden soll, wenn der Puffer leer wird g

@verständnisfrage:
Du hast bei deinem Programm keine einfachen Semaphoren mehr, sondern jeweils Semaphorenvektoren. Die kannst du aber genauso verwenden …

Der P-Operation entspricht dabei das “senken” und der V-Operation das “erhöhen”. Ist beim “Senken” nun der/ein Wert vorher schon auf 0, dann blockiert diese Funktion. Verlässt nun ein anderer Prozess/Thread den kritschen Bereich erhöht er den Wert (V) und somit läuft der blockierte Prozess weiter. Die beiden Operationen laufen atomar ab, weshalb es da keine Probleme bei gibt. Und es sind nur diese Dinge die atomar ablaufen, nicht das was zwischen P und V abläuft :slight_smile: (die CPU kann durchaus andere Dinge dazwischen machen, nur kann kein Prozess der ebenfalls die gleiche Semaphore (-vektor) verwendet dazwischen funken…

Anders ausgedrückt:
sem erniedrigen (P) [blockiert dann ggf]
schreiben/lesen/zeiger auf start oder ende neu setzen [kritischer Block]
sem erhöhen (V) [weckt ggf wartende Prozesse auf]

@getchar liest immer nur ganze Zeilen vom Terminal:
Man hätte doch aber dieses Jahr schon vorher allen sagen können wie man das abstellt. Letztes Jahr saßen viele verzweifelt vor ihren Rechnern und fragten sich warum den keines der Zeichen die man eingegeben hatte beim Verbraucher ankam … da ging viel zu viel Fehlersuchzeit drauf, die man besser für das Lösen der Aufgabe hätte verwenden können :slight_smile:

edit:
setvbuf(stdin, NULL, _IONBF, 0) sollte den stdinpuffer ausstellen … rein theoretisch. Die manpage davon behauptet es zumindest g
Leider funktioniert das nicht, aber die Übungsblätter zu Aufgabe 9 sind ja schon im Netz :slight_smile:


ahja.
gut dann hab ich erstmal alle falsch verstanden. is ja schonmal sehr motivierend.
mit anderen worten man macht sich eine binäre semaphore und macht die ringpuffer kontrollen (nicht anfang überschreiben, usw) mit if abfragen im krit bereich.
ich hab mir da sowas tollen überlegt wie wirs auch in der vl hatten. also eine 2dimensionale semaphore bei der das erste element den freien speicher zählt und das zweite den zu lesenden…
das prob an der sache is halt das es nicht klappt .))

naja. ich hab für hetue genug dummgeschwätzt…
weiß auch nicht wie ich auf den quatsch mitm terminieren komm…
aber ich muss trotzdem mal festestellen das solche sache echt SCHLECHT aus den übungsaufgaben hervorgehen… zumindest teilweise… naja…

danke jedefnalls


Das geht natürlich auch.
Allerdings würde ich dann eine 3-dimensionale Semaphore verwenden. Initialisiert wird sie mit den Werten Puffergröße,0,1. Im Erzeuger könntest du dann beim Betreten des kritischen Bereiches den erste und letzten Wert um 1 erniedrigen und beim Verlassen dann den mittleren und letzten Wert erhöhen. Dabei steht der erste Wert (wenn er 0 wird) für „Puffer voll“ (d.h. der Erzeuger sollte blockieren, der zweite für „Puffer leer“ (d.h. der Verbraucher sollte blockieren) und der dritte einfach nur für’s Betreten des kritischen Bereichs.
Damit ist dann auch klar was der Verbraucher mit dem Semaphorenvektor macht, oder? :slight_smile: (beim Betreten 2. und 3. erniedrigen, beim Verlassen 1. und 3. erhöhen).

Wenn ich mich jetzt nicht total verhauen habe und das so funktioniert, brauchst du im kritischen Block keine weiteren Kontrollen mehr, oder nicht? .

Wenn du ganz lustig bist, kannst du vermutlich auch noch den Start und das Ende .in der Semaphore speichern. Dazu wage ich aber kein gedankliches Experiment g

Sebbi


Die Idee mit der 2-dim. Semaphore ist schonmal gar nicht so schlecht.

Das mit dem krit. Bereich verbind ich immer mit einer binaeren P/V Sem. die alleine ist nicht der Weisheit letzter Schluss, schlieslich gibts hier 2 Synchronisationsprobleme (Schreiber darf nicht Leser ueberholen und umgekehrt) also muss es auch 2 Semaphoren geben, die blockieren koennen.

Mit dem Schreib und Lesezeiger haben die Semaphoren eigentlich nix zu tun.

[edit] natuerlich haben die was miteinander zu tun, aber ein Schreib/Lesezeiger kann/sollte nicht direkt als Semaphore realisiert werden.


das is mir grade beim kochen auch eingefallen :slight_smile:
wollt grad reinschreiben :))
ch glaub so mach ichs, sonst is das ganze gedankengut ja verschwendet :))

danke


muss man das hier alles verstehen??


ich glaub wenn man weniger als 60 punkte hat schon :-/


hrhr

was ist denn so unverstaendlich?


folgendes szenario:

mein verbraucher gibt den inhalt des ringpuffers nur aus, wenn der ringpuffer einmal voll geschrieben wurde… also(ringpuffer hat die größe 3) :
erzeuger:

h
j
k
verbraucher:
macht gar nichts!

aber …
erzeuger:

aaa
f
j
verbraucher:
aaa
f
i

… also immer ab dem zeitpunkt ab dem der ringpuffer mit einer zeile einmal voll geschrieben wurde funktionierts … hatte das problem schonmal jemand? was mach ich falsch?


wie pruefst du denn ob dein puffer ganz voll oder ganz leer ist? ueber semaphoren? dann richtig initialisieren. falls du dafuer ne eigene variable hast gilt das gleiche…


Ich hab auch noch eine Verständnisfrage zum Terminal. Wenn ich zwei oder mehr Zeichen eingebe und enter drücke, dann wird doch vom Zeilenbuffer von stdin das erste Zeichen genommen, und dann der Rest geflusht, oder? Das blöde ist, dass ich das mit dem DDD nicht rausbekomme, weil der ja immer nur ein Zeichen zulässt.


ok dummheit gehört bestraft !! mein fehler lag darin, dass ich im verbraucher, den schreib-, statt den lesezeiger verändert hab :wand:
aber jetzt gehts perfekt :smiley:


Robert: Irgendwie hab ich deine Frage jetzt nicht so richtig verstanden :wink:

Das Terminal liefert stdin erst ab, wenn man die Zeile z.B. mit Enter quittiert hat. Dann aber vollständig (Zeichen für Zeichen)…


zum erzeuger:

dieser soll bei einem EOF warten, bis der verbraucher alle zeichen aus dem puffer gelesen hat und ihm erst dann ein sigpipe schicken. wie implementiere ich dieses warten?
aktives warten ist ja nicht sinn der sache…


Also ich denke aktives warten ist diesem Fall nicht so schlimm, weil das ist ja eigentlich nur eine “Ausnahme”…

Ansonsten müsste man noch eine zusätzliche Semaphore einführen, oder?


wofuer braucht man da 2 semaphoren, ist das dafuer, was leonidas gerade vorgeschlagen hat?
ansonsten kannst du vielleicht etwas ausfuehrlicher werden :]?