19 Stimmen

Die Funktion open(2) bleibt beim Versuch, die serielle Schnittstelle unter MacOS zu öffnen, hängen

Ich bin auf ein Problem gestoßen, bei dem die Funktion open nie zurückkehrt, wenn ich versuche, eine serielle Schnittstelle zu öffnen. Es passiert nicht immer, und das Problem verschwindet für eine Weile, wenn ich meinen USB-Seriell-Adapter abziehe und wieder anschließe. Mein Code sieht wie folgt aus:

fileDescriptor = open(bsdPath, O_RDWR | O_NOCTTY);

wobei bsdPfad /dev/cu.KeySerial1 ist. Ich habe versucht, die Option O_NONBLOCK zum Befehl open hinzuzufügen, aber es bleibt immer noch hängen.

Natürlich würde ich gerne verstehen, warum das so ist. Ich glaube, dass, was auch immer das Problem ist, mit O_NONBLOCK sollte open auf jeden Fall zurückkehren, selbst wenn es nicht in der Lage war, den Port zu öffnen. Wenn es nicht in der Lage ist, den Port zu öffnen, sollte fileDescriptor -1 sein und errno gesetzt werden (ich überprüfe dies unmittelbar nach dem Aufruf von open). Natürlich geschieht dies nicht. Ist meine Vermutung falsch? Gibt es einen bekannten Grund dafür, dass open() nie zurückkehrt, selbst wenn O_NONBLOCK angegeben ist, wenn ein Fehler auftritt?

Mit der neuesten Version des Prolific PL-2303-Treibers und einem PL-2303-basierten USB-zu-Seriell-Adapter unter 10.7.2 konnte ich das Problem heute erneut reproduzieren. Ein paar Anmerkungen:

  • Aufgehängt im open() Aufrufs ist der Prozess nicht unterbrechbar durch Befehl-. (Steuerung-C).
  • Laufen ps -avx zeigt einen Prozessstatuscode von U für den Prozess an. Ich bin mir nicht sicher, was dieser Code bedeutet. Er erscheint nicht in den Manualseiten für ps gefunden durch Googeln. Es gibt keine Auflistung von Prozessstatuscodes in der Manpage für ps auf meinem Rechner. Vielleicht ist es spezifisch für die Mac-Version (10.4+?) von ps ?
  • Ich habe festgestellt, dass bei der Fahrt unmittelbar vor dem ersten Auftreten dieses Problems mein Anruf bei ioctl() um die Optionen des Anschlusses wieder in den Zustand zu versetzen, in dem sie waren, bevor ich sie für die Verwendung in meinem Programm geändert habe. Ich musste das Programm beenden (über den Debugger von Xcode). Unmittelbar danach, beim nächsten Start des Programms, open() hing...

5voto

Seth Noble Punkte 3223

Das Problem liegt wahrscheinlich im Gerätetreiber. Sie haben recht, wie O_NONBLOCK verhalten sollte, aber es ist Sache des Treibers, dies korrekt umzusetzen. Es wäre hilfreich zu wissen, welche Version von OS X und welches USB-Seriell-Gerät verwendet wird.

Die Standardverfahren bestehen darin, sicherzustellen, dass das Gerät direkt an die USB-Anschlüsse der CPU (und nicht an einen Hub) angeschlossen ist, die Kabel zu überprüfen und nach aktualisierten Treibern zu suchen.

Auch, wenn open() blockiert ist, ist der Prozess durch control-c unterbrechbar? Wenn Sie sich den Prozess mit " ps -aux ", während es blockiert ist, was bedeutet die " STAT "Feld sagen?

0 Stimmen

Danke für die Antwort. Ich habe das Problem mit einem Keyspan USA-19HS unter 10.6 und 10.7 beobachtet, und ich habe einen Bericht von einem Benutzer zusammen mit einem Stack-Trace erhalten, der das gleiche Problem mit einem PL-2303-basierten Adapter unter 10.7 zeigt. Ich werde versuchen, das Problem erneut zu reproduzieren, um die Antworten auf Ihre beiden Fragen zu finden.

0 Stimmen

Ich habe die Frage mit einigen neuen Beobachtungen aktualisiert. Nochmals vielen Dank.

1 Stimmen

U" bedeutet, dass der Prozess "ununterbrechbar" ist, was in der Regel bedeutet, dass er auf die Antwort eines Gerätetreibers wartet. OS X ist insofern ein wenig ungewöhnlich, als dass Treiber im Anwendungsbereich, außerhalb des Kernels, laufen können. Der Kernel übergibt Ihren open() y ioctl() den Treiber aufruft und dann Ihrem Prozess sagt, dass er auf das Ergebnis warten soll. Es hört sich so an, als ob sich der Treiber aufgehängt hat und Ihren Prozess hängen lässt (aber der Kernel ist sicher). Ich habe diesen Thread über den PL-2303 gefunden, der genau das tut, was Sie unter 10.7 Lion sehen. Vielleicht hilft er weiter: xbsd.nl/2011/07/pl2303-serial-usb-on-osx-lion.html

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X