Hallo, um printf()/scanf() auf einem Mikrocontrollersystem ans laufen zu bekommen, muss man unter GCC ja mindestens die Systemaufrufe für _read()/_write() implementieren und für STDIN/STDOUT/STDERR auf einen UART anpassen. Wenn man im Web nach Beispielen für die Implementierung sucht, dann findet man hauptsächlich (eigentlich nur) Implementierungen, welche _read() blockierend ausführen, d.h. es muss mindestens ein Zeichen empfangen worden sein. Das scheint ja für die meisten Anwender so zu funktionieren, aber wenn ich nun bspw. anstatt scanf() Funktionen für einzelne Zeichen (getchar(), getc(), etc) verwenden möchte und mir die Beschreibungen der Funktionen anschaue, dann können die auch EOF (= kein Zeichen empfangen = Rückgabewert 0) zurückliefern. Frage: wenn man's ganz richtig machen will, dann darf _read() demnach nicht blockierend ausgeführt sein und muss EOF bzw. 0 zurückliefern, wenn zum Aufrufzeitpunkt nichts empfangen ist, korrekt? Danke Ralf
Ralf schrieb: > dann können die auch EOF (= kein Zeichen empfangen = Rückgabewert 0) > zurückliefern. Aber nur im Fehlerfall oder eben bei End Of File. Wenn einfach nur keine Zeichen da sind, soll _read() blockieren. Wie sonst soll scanf() darauf warten, dass alles angekommen ist?
Niklas G. schrieb: > Ralf schrieb: >> dann können die auch EOF (= kein Zeichen empfangen = Rückgabewert 0) >> zurückliefern. Korrektur: Ich hab hier einen Fehler, EOF ist nicht 0, sondern -1. > Aber nur im Fehlerfall oder eben bei End Of File. Wenn einfach nur keine > Zeichen da sind, soll _read() blockieren. Wie sonst soll scanf() darauf > warten, dass alles angekommen ist? Meine Vermutung(!) wäre, dass scanf() _read() solange aufruft bis != EOF zurückgegeben wird. Ralf
Ralf schrieb: > Meine Vermutung(!) wäre, dass scanf() _read() solange aufruft bis != EOF > zurückgegeben wird. Nene, das wäre ja super ineffizient. Bei EOF kehrt scanf() sofort zurück. Schau doch in den Sourcecode von scanf()...
Niklas G. schrieb: > Ralf schrieb: >> Meine Vermutung(!) wäre, dass scanf() _read() solange aufruft bis != EOF >> zurückgegeben wird. > Nene, das wäre ja super ineffizient. Bei EOF kehrt scanf() sofort > zurück. Schau doch in den Sourcecode von scanf()... Dann versteh ich nicht, unter welchen Umständen getchar() überhaupt EOF zurückgibt, wenn STDIN als Eingabe verwendet wird? Bei getc() ist es klar, das bekommt einen FileDescriptor mitgeteilt, da kann (wird) EOF dann vorkommen. Für den Sourcecode meinst du sourceware.org? Ich schau mal ob ich mich da zurechtfinde :) Vielleicht sollte ich besser schildern, was ich vorhabe: ich möchte einzelne Zeichen vom UART lesen - alle Zeichen bis auf ein spezielles sollen ganz normal weiter an eine andere Funktion durchgereicht werden. Wenn das spezielle Zeichen empfangen wird, dann soll über eine bestimmte Zeit geprüft werden, ob weitere Zeichen empfangen wurden oder nicht. Wenn ja, alles inklusive des speziellen Zeichens weiter durchreichen, ansonsten eben was spezielles machen. Also im Prinzip beim Empfang des speziellen Zeichens einen Timeout auf den Empfang weiterer Zeichen einrichten. Mit einem nicht blockierenden _read() unter der Haube, welches EOF für "keine Daten vorhanden" ausspuckt hätte ich nun gedacht, dass das gehen könnte, bspw. mit getchar(). Also mal der aktuelle Fragenkatalog: 1) _read() muss blockierend sein und kann kein EOF liefern? 2) Unter welchen Umständen spuckt getchar() dann ein EOF aus, wenn dieses nicht von _write() kommen kann? 3) Wie richtet man eine nicht blockierende Abfrage von STDIN ein? getc()/getchar() in Kombination mit ungetc() auf STDIN? Ralf
Hab da grad nochmal genauer drüber nachgedacht:
> 1) _read() muss blockierend sein und kann kein EOF liefern?
Anstatt EOF für keine Daten würde ja 0 auch gehen, wenn nichts im Buffer
ist - read() gibt ja die Menge der gelesenen Daten zurück. Kommt scanf()
dann eher damit klar? Das würde es scanf() auch ermöglichen zu prüfen ob
was angekommen ist. Damit wäre es aber trotzdem nicht blockierend.
Ralf
Ralf schrieb: > Dann versteh ich nicht, unter welchen Umständen getchar() überhaupt EOF > zurückgibt, wenn STDIN als Eingabe verwendet wird? Wenn stdin geschlossen wurde oder "am Ende angekommen" ist, oder bei einem Fehler. stdin muss ja nicht von z.B. einer RS232 kommen, sondern kann auch aus einer Datei lesen. Bei Kommandozeilentools auf dem Rechner ist das nicht so ungewöhnlich. Und wenn das Ende dieser Datei erreicht ist, kommt halt ein EOF. > Bei getc() ist es klar, das bekommt einen FileDescriptor mitgeteilt, da > kann (wird) EOF dann vorkommen. getchar ist nix anderes als getc(stdin). > 3) Wie richtet man eine nicht blockierende Abfrage von STDIN ein? > getc()/getchar() in Kombination mit ungetc() auf STDIN? Nein. In Standard-C gibt's keinen Weg dafür. Ralf schrieb: >> 1) _read() muss blockierend sein und kann kein EOF liefern? > Anstatt EOF für keine Daten würde ja 0 auch gehen, wenn nichts im Buffer > ist - read() gibt ja die Menge der gelesenen Daten zurück. Ja, und wenn es keine Daten mehr lesen kann, liefert es das zurück, was dann bedeutet, dass das EOF erreicht ist. Wenn gerade keine Daten verfügbar sind, liefert es nichts zurück, weil es blockiert.
:
Bearbeitet durch User
Rolf M. schrieb: >> 3) Wie richtet man eine nicht blockierende Abfrage von STDIN ein? >> getc()/getchar() in Kombination mit ungetc() auf STDIN? > Nein. In Standard-C gibt's keinen Weg dafür. Das ist wohl korrekt, wie ich mittlerweile feststellen musste. > Ralf schrieb: >>> 1) _read() muss blockierend sein und kann kein EOF liefern? >> Anstatt EOF für keine Daten würde ja 0 auch gehen, wenn nichts im Buffer >> ist - read() gibt ja die Menge der gelesenen Daten zurück. > Ja, und wenn es keine Daten mehr lesen kann, liefert es das zurück, was > dann bedeutet, dass das EOF erreicht ist. Wenn gerade keine Daten > verfügbar sind, liefert es nichts zurück, weil es blockiert. Habe den von Niklas implizierten Versuch durchgeführt, also scanf() mit einem nicht blockierenden _read() - scanf() ist wie von Niklas erwartet sang- und klanglos durchgerauscht :) Ich muss mir mal überlegen wie ich das lösen kann. Notfalls muss ich eben doch den UART-Puffer vorher prüfen ob was drin ist, das wollte ich eigentlich vermeiden. Danke euch beiden. Ralf
Ralf schrieb: > Wenn man im Web nach Beispielen für die Implementierung sucht, dann > findet man hauptsächlich (eigentlich nur) Implementierungen, welche > _read() blockierend ausführen, d.h. es muss mindestens ein Zeichen > empfangen worden sein. Das ist korrekt, read() blockiert standardmäßig. Es ist aber kein Problem, noch eine ioctl()-Funktion hinzuzufügen, mit welcher man ein Flag setzen kann, dass read() ab sofort nicht mehr blockieren soll. Unix/Linux machen es so. Dieses Vorgehen kann problemlos auf einem µC analog dazu implementiert werden.
Frank M. schrieb: > Das ist korrekt, read() blockiert standardmäßig. Es ist aber kein > Problem, noch eine ioctl()-Funktion hinzuzufügen, mit welcher man ein > Flag setzen kann, dass read() ab sofort nicht mehr blockieren soll. > Unix/Linux machen es so. Dieses Vorgehen kann problemlos auf einem µC > analog dazu implementiert werden. Standardfunktionen wie scanf() werden aber trotzdem nicht funktionieren, wenn man denen hinterrücks den stream non-blocking macht.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.