2013-05-19 13 views
5

In einem Multi-Thread-Linux-Programm für die serielle Kommunikation ist es möglich (und was wäre der beste Ansatz), eine blockierende read() -Aufruf von einem anderen Thread zu beenden?Linux, Cancel Blocking lesen()

Ich möchte alles so reaktiv wie möglich halten und die Verwendung von Timeouts mit wiederholten Abfragen vermeiden.

Der Hintergrund dieser Frage ist, dass ich versuche, eine serielle Scala-Kommunikationsbibliothek für Linux mit JNI zu erstellen. Ich versuche, die native Seite so einfach wie möglich zu halten, indem ich unter anderem eine read() und close() Funktion zur Verfügung stelle. Auf der Scala-Seite würde ein Thread read() aufrufen und blockieren, bis Daten von der seriellen Schnittstelle verfügbar sind. Der serielle Port kann jedoch auf andere Weise geschlossen werden, was zu einem Aufruf von close() führt. Um den blockierten Thread freizugeben, müsste ich den Systemleseanruf irgendwie abbrechen.

+0

https://stackoverflow.com/questions/384391/how-to-signal-select-to-return-unmittelbar –

Antwort

7

Ein ziemlich populärer Trick: Anstatt in read() zu blockieren, blockieren Sie in select() sowohl an Ihrer seriellen Buchse als auch an einer Pipe. Wenn ein anderer Thread den Thread aufwecken möchte, kann er dies tun, indem er ein Byte an das andere Ende der Pipe schreibt. Durch dieses Byte wird select() zurückgegeben und der Thread kann nun bereinigen und beenden oder was immer er tun muss. (Beachten Sie, dass Sie den seriell-Socket möglicherweise nicht blockieren lassen möchten, damit dies zu 100% zuverlässig funktioniert. Damit wird sichergestellt, dass Ihr Thread nur in select() und niemals in read() blockiert)

+1

abgeordnet. Ich mache fast alle meine Multithread-Programmierung auf diese Weise. Es ist ein Muster direkt aus der Kommunikation sequenzieller Prozesse (CSP). Angesichts der Tatsache, dass Scala Communicating Scala Objects (eine praktische Umsetzung von CSP), denke ich, Sie Vorschlag ist sehr angemessen. BTW der größte Nachteil der Programmierung für Windows Win32 oder .NET ist, dass Sie nicht() auf Pipes, eine massive Unterlassung auswählen können. MS würde Sie glauben lassen, dass async IO besser ist, aber es führt zu wirklich chaotischen Code. Das Cygwin-Projekt hatte Probleme beim Schreiben von select(). Ihre Lösung beinhaltet eine Menge Threads und Abfragen. – bazza

+0

FWIW können Sie den gleichen Trick (mit nur 10 mal den Aufwand;)) unter Windows durch Erstellen von zwei TCP-Sockets und verbinden() eines von ihnen mit dem anderen, wie hier gezeigt: http://code.google.com /p/imagesoft/source/browse/trunk/rpcrt4/socketpair.c?r=5 –

+1

Danke für die Antwort! Select funktionierte nicht für mich (vielleicht habe ich etwas falsch gemacht), aber beim Lesen von select() man pages stolperte ich über poll(). Das hat perfekt funktioniert :) –

4

AFAIK-Signale sind die einzige Möglichkeit, einen Thread aus einem blockierenden Systemaufruf zu entfernen.

Verwenden Sie eine pthread_kill(), die auf den Thread mit einem USR1-Signal gerichtet ist.

+0

Danke für die Antwort, aber ein pthread_kill wäre in meinem Anwendungsfall nicht möglich (da die Funktionen von aufgerufen werden verschiedene Threads einer JVM). Gibt es Workarounds, die ich verwenden könnte? Ich habe einiges über Epoll gehört, aber meine Tests haben auch nicht funktioniert. –

+0

Ich weiß nicht genug über JNI, um eine Empfehlung zu machen. Sie könnten 'epoll' aus einem Thread und' close() 'aus einem anderen Thread verwenden, aber ich glaube, das ist undefiniertes Verhalten. – kja