aufgabe 9 mit eigener (schlechter :)?) 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 9 mit eigener (schlechter :)?) aufgabe 8?
hi,

wie ist das eigentlich, wenn man in der aufgabe 8 fehler gemacht hat
und mit dieser loesung als vorlage die aufgabe 9 macht:
wird dann praktisch nur der unterschied betrachtet, also ob man alles korrekt aendert?

die musterloesung finde ich naemlich etwas unuebersichtlich,
aber bei meiner weiss ich natuerlich nicht, ob da so alles 100%ig passt…


hmm was genau findest du unübersichtlich? im endeffekt kann dir die lösung egal sein (ok umgekehrt uns eigentlich auch :wink: ), du musst ja nur im erzeuger den getc und im verbraucher den putc durch eigene methoden ersetzen die ungepuffert arbeiten… der rest kann dir eigentlich egal sein


na gut :] - wenn’s sein muss. ich seh schon ein, dass es bloed fuer euch ist, unsere dummen und wahrscheinlich sehr unterschiedlichen loesungen zu durchforsten :].

btw eine andere frage:
settings.c_lflag &= ~ICANON;

was macht genau das &=? ich meine, dass es irgendwas mit bitweiser verknuepfung zu tun hat, weiss es aber nicht mehr sicher. und was macht die tilde vor dem ICANON? ist das eine verneinung?


jup, ~ ist die bitweise negation. &= ist wie += ein abgeleiteter operator:

settings.c_lflag &= ~ICANON; settings.c_lflag = settings.c_lflag & ~ICANON; settings.c_lflag = settings.c_lflag & ~0000002; settings.c_lflag = settings.c_lflag & ~000 000 000 000 000 010; settings.c_lflag = settings.c_lflag & 111 111 111 111 111 101;

egal was vorher in settings.c_lflag stand, das ICANON bit ist hinterher nicht mehr gesetzt. hth

hinterher dann settings.c_lflag |= ICANON;


vielen dank fuer die sehr ausfuehrliche erklaerung!
das rekonstruieren hab ich ueber ein backup-struct gemacht… vielleicht ein bisschen kompliziert…

zur version 3.x:
auf welchen wert soll ich da VMIN setzen? eigentlich muesste man ihn auf unendlich setzen, sodass er die anzahl der zeichen ignoriert und nur nach der zeit (hier eine halbe sekunde) geht…


hmm der argumentation kann ich nicht ganz folgen wenn VMIN unendlich wäre müssten mindestens unendlich zeichen eingegeben worden sein? Einfach auf 1 belassen


Auch wenn ich jetzt Majestätsbeleidigung riskiere: VMIN=1 funktioniert bei mir nicht. Dadurch werden die Zeichen sofort übergeben. VMIN=2 werden die Zeichen nach 2 Eingaben übergeben. Auch ohne Rücksicht auf meinen Zeitwert. Ich muss VMIN also so hoch einstellen, dass ich in 0,5 Sekunden diesen Wert an Zeichen nicht tippen kann.

Ich bin übrigens nicht der einzige, der dieses Problem hatte.


Auch das hilft hier nicht weiter, weil die 0,5s nur den zeitlichen Abstand zwischen 2 Tastenanschlägen ausmachen. ich hab z.B. VMIN auf 100 und wenn ich auf der Taste bleib, wird genau nach 100 Zeichen gesendet. Wenn ich natürlich mal 0,5s Pause dazwischen mach, sendet er das auch gleich dann.

Zu dem Zurücksetzen: muss man sowas tun? Ich hab’s bis jetzt noch net drin und funzt trotzdem alles sauber. Ich mein die Shell wird sich das eh so einstellen, wie sie’s braucht. Und mit nem Zeilenmodus kann die kaum was anfangen.

Nochwas dazu: eigentlich müsste man das tcsetattr-Zeug vor jedem getc machen, weil als ich mit ^Z und fg mal kurz aus dem job raus bin, war nachher wieder VMIN=1,VTIME=0 eingestellt. Er hat jedenfalls nicht mehr gewartet mit dem Senden. Da, selbst die Jobverwaltung setzt das nicht wieder sauber zurück! :-p


Hast auch wieder Recht…ok…VMIN=1 geht net, VMIN=100 ist auch net optimal. Also was IST jetzt richtig??


Naja, vielleicht gibt ja irgendwo ein define MAX_KEYS_A_HUMAN_CAN_TYPE_IN_A_SECOND oder so :slight_smile:

Aber nochmal zu getc/putc: Warum muss ich denn da eigene Methoden schreiben? Kann ich nicht beim erzeugen des Erzeugers die Flags setzten und beim beenden Rückgängig machen?


zum VMIN/VTIME-Problem in 3c:
[hab den Abschnitt in der man-page jetzt auch erst drei mal lesen muessen :slight_smile: ].

VMIN=100, VTIME=5 bedeutet z.B.,
sobald das erste Zeichen gelesen wird, wird der Timer
gestartet.
Kommt bis zum Ablauf des Timers nach 0,5s kein weiteres
Zeichen, kommt read mit dem einen gelesenen Zeichen
zurueck.
Tippt man innerhalb der 0,5s wieder ein Zeichen, wird der
Timer zurueckgesetzt und laeuft neu los.
Spaetestens nach 100 Zeichen oder wenn man mal laenger
als 0,5s Pause zwischen 2 Zeichen gemacht hat, kommt
der read mit all dem was bis dahin einegegeben wurde
zurueck.
[VMIN heisst nicht, dass diese Zeichenzahl innerhalb von 0,5s
getippt werden muss damit er sie zureuckliefert

  • nach jedem Zeichen wird der Timer ja ohnehin zurueckgesetzt -
    VMIN bedeutet, dass diese Zeichenzahl
    gepuffert wird so lange der Timer nicht einmal ablaeuft.
    Insofern trifft die Idee mit dem
    MAX_KEYS_A_HUMAN_CAN_TYPE_IN_A_SECOND
    daneben ].

VMIN=1 ist damit natuerlich Unsinn, weil das immer nach
einem Zeichen zurueckkommt.

Ich wuerde VMIN auf die Groesse meines read-Puffers
setzen - mehr kann ich ohnehin nicht auf einmal lesen -
und wenn der Benutzer zwischen drin einpennt, bekomm’ ich halt
was bis dahin da ist.


wieso eigene Methoden schreiben?
Das Problem ist nur, dass putc in der stdio-library-Funtkion (nciht im Treiber!) eine
Zeilenpufferung macht. Wenn man nach putc jeweils
fflush aufruft, dann wird dieser Puffer jeweils sofort rausgeschrieben.
Alternativ kann man natuerlich den write-Systemcall statt putc benutzen
(dann natuerlich nicht mit stdout sondern mit fileno(stdout) - write will ja
keinen FILE-Pointer sondern einen Filedescriptor) - da wird dann sowieso
nichts gepuffert.

Dritte Moeglichkeit: man schaltet mit setbuf(stdout, NULL) die
Pufferung auf stdout aus.


THX!!! Klingt logisch und werd ich gleich machen.


Richtig, das ist ein ganz gravierendes Problem, das man nur deshalb meist nciht
merkt, weil die tcsh ohnehin immer ihre eigene Einstellung des
terminaltreibers erzwingt.
Die Terminalparameter sind ja keine Prozessattribute sondern gelten global fuer
alle Prozesse die mit dem terminal arbeiten. Wenn das einer verstellt haben die anderen
u.U. ein Problem.
Wenn man aus einer csh so ein Programm startet und das dan stoppt ist in der
Tat der Treiber auch in der csh noch total verstellt.

Loesung (macht z.B. der vi so): Man schreibt einen Signalhandler fuer
SIGTSTP und stellt im Signalhandler den Terminaltreiber wieder richtig wie er vorher war.
Einziges Problem: der Prozess soll ja stoppen - wenn ich einen handler fuer das
Signal schreibe, dann tut er das aber nicht mehr. Entweder man schickt sich aus
dem SIGTSTP-Handler ein SIGSTOP (das ist aber nicht ganz sauber, weil der Benutzer
ja ein SIGTSTP ausgeloest hat und es zu Verwirrung kommen kann, wenn der
Prozess dann auf einmal mit SIGSTOP anhaelt), oder:
Man setzt im SIGTSTP-Handler den handler auf DEFAULT zurueck,
deblockiert (mit sigprocmask) das im handler ja blockierte SIGTSTP und schickt
sich aus dem handler mit kill nochmal ein SIGTSTP. Das schlaegt dann sofort durch und
stoppt den Prosess mitten im SIGTSTP-handler.

Wenn er dann ein SIGCONT bekommt, laeuft er genau an dieser stelle in SGTSTP-handler
weiter, setzt den handler mit sigaction wieder richtig auf, stellt den Terminaltreiber wieder
auf die eigenen Wuensche ein und kommt zurueck.


Also, für den Verbraucher wäre ja dann meine methode eine, die den putc und fflush enthält. Aber wie ist das mit dem Verbraucher? Da brauch ich doch einfach Anfang ~ICANON, VMIN, VTIME entsprechend setzen. Dann muss ich am getc nichts mehr ändern. (Halt dann noch aufpassen, dass die eintellungen am Terminal rückgängig gemacht werden.


du meinst den erzeuger :]. und da langt es meiner meinung nach, wenn man das macht, was du beschrieben hast…


wie gross ist denn dieser puffer? ich benutze wie gewuenscht die i4sp-loesung der aufgabe 8 als basis und dort wird kein read sondern getc () verwendet. da gibt es doch dann keinen wirklichen puffer, oder?

und braucht man den ganzen schmonz mit dem stop-handler wirklich? ich waere z. b. gar nicht auf die idee gekommen, das auszuprobieren…


Naja, da die tcsh und die bash anscheinend auch ihre eigenen Terminaltreiber/ -einstellungen haben sollte das ja dann wohl wurscht sein.


in der common.h ist die BUFSIZE angegeben. Ist halt die groesse des Puffers im shm-Segment.