Hallo, ich habe ein kleines C-Program für Linux geschreiben. In der Hauptschleife wird mittels Select auf eine einkommende TCP-Verbindung und gleichzeitig auf Daten von der seriellen Schnittstelle gewartet. Das läuft auch super, ABER: wenn das Serielle-Device entfernt wird (USB-Serial-Adapter) weckt select permanent den Thread auf. Wenn ich die Daten abhole ist immer 1Byte im Buffer. Ich erkenne das akt. in dem ich Zähle wie häufig 1Byte empfangen wurde. Ab einer Grenze wird das Device als nicht mehr vorhanden angesehen.Ich kann das Device nicht schließen und neu öffnen. Das gibt ein segfault wenn das Device weg ist. Aber das wirkt auf mich unsauber. Kann ich irgendwie an den von Select veränderten Strukturen erkennen ob das Device noch lebt? Oder gibt es hierfür eine andere Möglichkeit. Gruß Snowyrain
Hallo Snowyrain, bin zwar kein Linux-Experte, aber sollte select() nicht einen Fehler zurückgeben, wenn das Device entfernt wird? MfG Mark
Hatte select() nicht auch ein FD-Set für Dateideskriptoren, die durch Fehler auffallen? Und für read() gibts doch errno-Werte.
Hallo, vielen Dank für die Antworten. exceptfds und errno stehen jetzt auf meiner zuerlernen Liste. Vielen Dank Snowyrain
Hallo, select und read sollten doch eigentliche -1 zurückliefern wenn etwas nicht stimmt? oder?!? Wenn ich das device entferne liefert select ständig 1 und read ständig 0. Und strerror(errno) liefert ständig ein "Success". Irgendwie scheint select nicht mit entfernten Geräten klarzukommen. Ich würde nach dem Select-Aufruf (, also nachdem select den Thread weckt,) überprüfen ob die Devices noch leben. Gibts dafür Befehle, eine Art Ping für Devices?!? Gruß Snowyrain
Hallo Snowyrain! Von einem ping fuer devices ist mir nichts bekannt. Vorschlag: select==1 und read==0 als Entfernen des Geraetes interpretieren. Dann sofort schließen und aus der Selectliste rausnehmen, anschließend eine Zeit lang abwarten, dann aber in bestimmten Zeitabständen versuchen, das device neu zu oeffnen.
Hallo, so habe ich es gemacht. Zudem habe ich den gesuchten "ping" gefunden. Ich frage die Attribute der seriellen Schnittstelle ab [tcgetattr()]. Vielen Dank Gruß Snowyrain
Danke Dir auch, denn das mit dem tcgetattr() hatte ich vorher nicht so im Kopf. Aber an welcher Stelle setzt Du es denn ein? Ich vermute mal innerhalb des select(), bin mir da aber nicht sicher. Gruß Micky
Hallo, termios.h stellt u.a. die Funktion tcgetattr() zur Verfügung. Ich frage hiermit einfach die Einstellungen des seriellen Ports ab. Wenn das fehlschlägt stimmt was mit der Schnittstelle nicht. Ich belege select() mit einem Timeout. Zur Zeit alle 20Sek, ich werde später wohl auf >300Sek gehen. Jetzt wird der Errno-Wert und welchen Wert select zurück gibt überprüft. Zudem wird tcgetattr() aufgerufen, als zusätzliche Kontrolle. Wenn etwas nicht stimmt wird die serielle Schnittstelle geschlossen und neu geöffnet. Auf einem PC läuft das auch sehr stabil. Gruß Snowyrain
Ich bin mir jetzt nicht ganz sicher, aber war das nicht so, daß beim Schließen einer (Lese-) Verbindung select() aufwacht und das Lesen eines Zeichens dann den Wert -1 alias EOF liefert (als int, also von jedem tatsächlichen Zeichen unterscheidbar)? Vielleicht hast du das Problem ja nur, weil du den von getc() gelieferten Wert nicht als int mit EOF vergleichst, bevor du ein char daraus machst? Welches ist denn das eine Byte, das du beim Schließen bekommst? Wenn es so ist, wie ich vermute, dann ist die Lösung relativ einfach: Wie gewohnt mit select() warten, wenn select() zurückkehrt vom jeweiligen Device eine int mit getc() oder fgetc() lesen. Falls diese int ==EOF ist, Datei schließen und vergessen. Wenn nicht, dann zu char casten und als gelesenes Zeichen verwenden.
So, habe eben mal 'man 2 select' gelesen. Es ist tatsächlich so, daß es das dokumentierte Verhalten von select() ist: Dateiende an einem Input-fd führt zu einem Rücksprung von select() und ein anschließendes Lesen scheitert. Genau das ist dann das Zeichen dafür, die Datei schließen und vergessen zu können. Man muß sie natürlich dann auch aus dem Satz der FDs für den nächsten select()-Aufruf entfernen und hat dann seine Ruhe.
Hallo, dass mit dem EOF klingt gut. Ich werde es die Tage testen. Es würde meinen Code echt lesbarer machen. Und vor allem vernünftig. Vielen Dank, ich melde mich wenn ich mehrt weiß Snowyrain
das mit EOF ist eine kleine falle. wenn z.b. ein usb-seriell-adapter angeschlossen ist und du ein programm laufen hast, das das device offen hält und du dann den wandler abziehst, dann kehrt select() sofort zurück aber read() liefert 0 byte und sussess!
EOF bekommt man doch nicht von read(), sondern wenn man getc() oder fgetc() aufruft. read() liefert im Fehlerfall 0 stattdessen, ja. Ich baue zwar gerne Fallen, aber hier sehe ich keine. Habe ich etwas übersehen? Sussess?
sorry, typo. read sollte irgendeinen fehler liefern, tut es aber nicht.
Was lieferte denn dann? 0? Genau das ist der gemeldete Fehler! Wenn select() für einen fd Lesebereitschaft signalisiert, das anschließende Lesen aber nichts liefert (EOF bei getc()/fgetc(), 0 bei read()), dann ist das genau der Tip, den fd in die Tonne treten zu können und die Datei zu schließen. (Liefert read() nicht 0 (nichts gelesen) und auch nichts >0 (Anzahl gelesener Byte), sondern -1, dann ist das ebenfalls als Fehler zu sehen und zusätzlich kann man errno auswerten (und danach hoffentlich wieder zu 0 setzen). Lt. snowyrain liefert aber select() 1 und read() 0, und genau das ist doch das der erste Fall.) aus man 2 read:
1 | RETURN VALUE |
2 | On success, the number of bytes read is returned (zero indicates end of file), |
3 | and the file position is advanced by this number. It is not an error if this |
4 | number is smaller than the number of bytes requested; this may happen for exam‐ |
5 | ple because fewer bytes are actually available right now (maybe because we were |
6 | close to end-of-file, or because we are reading from a pipe, or from a termi‐ |
7 | nal), or because read() was interrupted by a signal. On error, -1 is returned, |
8 | and errno is set appropriately. In this case it is left unspecified whether the |
9 | file position (if any) changes. |
Am Dateiende (bzw. nicht mehr existierender Verbindung, je nach Device) wird 0 geliefert, und das nicht als Fehler betrachtet.
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.