Laut manpage open(2) können Sie O_RDONLY|O_NONBLOCK übergeben oder O_WRONLY|O_NONBLOCK um die open zu vermeiden Systemaufruf blockiert werden (Sie erhalten errno == ENXIO in diesem Fall)
Wie ich kommentiert habe, lesen Sie auch die Manpages fifo(7) und mkfifo(3).
Zuerst einige Vorbereitungen:
Mit O_NONBLOCK und poll() ist gängige Praxis – nicht umgekehrt. Um erfolgreich zu arbeiten, müssen Sie sicherstellen, dass alle poll() verarbeitet werden und read() Rückgabezustände korrekt:
read()Rückgabewert von0bedeutet EOF - die andere Seite hat ihre Verbindung geschlossen. Dies entspricht (normalerweise, aber nicht auf allen Betriebssystemen)poll()Rückgabe einesPOLLHUPrevent. Vielleicht möchten Sie nachPOLLHUPsuchen bevor Sieread()versuchen , ist aber seitread()nicht zwingend erforderlich gibt garantiert0zurück nach dem Schließen der Schreibseite.- Wenn Sie
read()anrufen bevor sich ein Autor verbunden hat, und Sie habenO_RDONLY | O_NONBLOCK, erhalten Sie EOF (read()Zurückgeben von0) wiederholt, wie Sie bemerkt haben. Wenn Sie jedochpoll()verwenden um aufPOLLINzu warten Ereignis vor dem Aufruf vonread(), wartet er darauf, dass der Writer eine Verbindung herstellt, und erzeugt keine EOFs. read()Rückgabewert-1bedeutet normalerweise Fehler. Wenn jedocherrno == EAGAIN, bedeutet dies einfach, dass im Moment keine Daten mehr verfügbar sind und Sie nicht blockieren, sodass Sie zupoll()zurückkehren können falls andere Geräte behandelt werden müssen. Wennerrno == EINTR, dannread()wurde vor dem Lesen von Daten unterbrochen, und Sie können entweder zupoll()zurückkehren oder rufen Sie einfachread()an sofort wieder.
Jetzt für Linux:
- Wenn Sie auf der Leseseite mit
O_RDONLYöffnen , dann:- Der
open()blockiert, bis ein entsprechender Writer geöffnet ist. poll()ergibt einenPOLLINrevent, wenn Daten zum Lesen bereit sind oder EOF auftritt.read()blockiert, bis entweder die angeforderte Anzahl von Bytes gelesen wurde, die Verbindung geschlossen wird (0 zurückgibt), sie durch ein Signal unterbrochen wird oder ein schwerwiegender E/A-Fehler auftritt. Diese Blockierung macht den Zweck der Verwendung vonpoll()zunichte , weshalbpoll()wird fast immer mitO_NONBLOCKverwendet . Sie könnten einenalarm()verwenden um ausread()aufzuwachen nach einem Timeout, aber das ist zu kompliziert.- Wenn der Schreiber schließt, erhält der Leser einen
poll()POLLHUPrevent undread()gibt0zurück danach auf unbestimmte Zeit. An diesem Punkt muss der Reader sein Dateihandle schließen und erneut öffnen.
- Der
- Wenn Sie auf der Leseseite mit
O_RDONLY | O_NONBLOCKöffnen , dann:- Der
open()wird nicht blockiert. poll()gibt einenPOLLINaus revent, wenn Daten zum Lesen bereit sind oder EOF auftritt.poll()blockiert auch, bis ein Autor verfügbar ist, falls keiner vorhanden ist.- Nachdem alle aktuell verfügbaren Daten gelesen wurden,
read()gibt entweder -1 zurück und setzterrno == EAGAINwenn die Verbindung noch offen ist, oder es wird0zurückgegeben wenn die Verbindung geschlossen (EOF) oder noch nicht von einem Schreiber geöffnet ist . Wennerrno == EAGAIN, das bedeutet, dass es Zeit ist, zupoll()zurückzukehren , da die Verbindung geöffnet ist, aber keine Daten mehr vorhanden sind. Wennerrno == EINTR,read()hat noch keine Bytes gelesen und wurde durch ein Signal unterbrochen, kann also neu gestartet werden. - Wenn der Schreiber schließt, erhält der Leser einen
poll()POLLHUPrevent undread()gibt0zurück danach auf unbestimmte Zeit. An diesem Punkt muss der Reader sein Dateihandle schließen und erneut öffnen.
- Der
- (Linux-spezifisch:) Öffnet man auf der Leseseite mit
O_RDWR, dann:- Der
open()wird nicht blockiert. poll()ergibt einenPOLLINneu starten, wenn die Daten zum Lesen bereit sind. Für benannte Pipes verursacht EOF jedoch nichtPOLLINoderPOLLHUPEinnahmen.read()blockiert, bis die angeforderte Anzahl von Bytes gelesen wurde, es durch ein Signal unterbrochen wird oder ein anderer schwerwiegender E/A-Fehler auftritt. Für benannte Pipes wirderrno == EAGAINnicht zurückgegeben , noch wird es0zurückgeben einer von. Es bleibt einfach dort, bis die genaue Anzahl der angeforderten Bytes gelesen wurde oder bis es ein Signal empfängt (in diesem Fall gibt es die Anzahl der bisher gelesenen Bytes zurück oder gibt -1 zurück und setzterrno == EINTRwenn noch keine Bytes gelesen wurden).- Wenn der Writer schließt, verliert der Reader nicht die Fähigkeit, die Named Pipe später zu lesen, wenn ein anderer Writer die Named Pipe öffnet, aber der Reader erhält auch keine Benachrichtigung.
- Der
- (Linux-spezifisch:) Öffnet man auf der Leseseite mit
O_RDWR | O_NONBLOCK, dann:- Die
open()wird nicht blockiert. poll()gibt einenPOLLINneu starten, wenn die Daten zum Lesen bereit sind. EOF verursacht jedoch nichtPOLLINoderPOLLHUPnutzt Named Pipes.- Nachdem alle aktuell verfügbaren Daten gelesen wurden,
read()gibt-1zurück und setzen Sieerrno == EAGAIN. Dies ist die Zeit, zupoll()zurückzukehren um auf weitere Daten zu warten, möglicherweise von anderen Streams. - Wenn der Writer schließt, verliert der Leser nicht die Fähigkeit, die Named Pipe später zu lesen, wenn ein anderer Writer die Named Pipe öffnet. Die Verbindung ist dauerhaft.
- Die
Wie Sie zu Recht befürchten, verwenden Sie O_RDWR mit Pipes ist kein Standard, POSIX oder anderswo.
Da diese Frage jedoch häufig aufzutauchen scheint, ist der beste Weg unter Linux, "widerstandsfähige Named Pipes" zu erstellen, die auch dann am Leben bleiben, wenn eine Seite geschlossen wird, und die nicht POLLHUP verursachen revents oder gibt 0 zurück für read() , soll O_RDWR | O_NONBLOCK verwenden .
Ich sehe drei Hauptwege für den Umgang mit Named Pipes unter Linux:
-
(Tragbar.) Ohne
poll(), und mit einer einzelnen Pipe:open(pipe, O_RDONLY);- Hauptschleife:
read()so viele Daten wie nötig, möglicherweise Schleife aufread()Anrufe.- Falls
read() == -1underrno == EINTR,read()immer wieder. - Falls
read() == 0, die Verbindung wird geschlossen und alle Daten wurden empfangen.
- Falls
-
(Tragbar.) Mit
poll(), und mit der Erwartung, dass Pipes, selbst benannte, nur einmal geöffnet werden und dass, sobald sie geschlossen sind, sowohl vom Leser als auch vom Schreiber wieder geöffnet werden müssen, wodurch eine neue Pipeline eingerichtet wird:open(pipe, O_RDONLY | O_NONBLOCK);- Hauptschleife:
poll()fürPOLLINEreignisse, möglicherweise auf mehreren Pipes gleichzeitig. (Hinweis:Dies verhindertread()davor, mehrere EOFs zu erhalten, bevor ein Schreiber eine Verbindung hergestellt hat.)read()so viele Daten wie nötig, möglicherweise Schleife aufread()Anrufe.- Wenn
read() == -1underrno == EAGAIN, gehen Sie zurück zupoll()Schritt. - Falls
read() == -1underrno == EINTR,read()immer wieder. - Falls
read() == 0, wird die Verbindung geschlossen, und Sie müssen die Pipe beenden oder schließen und erneut öffnen.
- Wenn
-
(Nicht portierbar, Linux-spezifisch.) Mit
poll(), und mit der Erwartung, dass Named Pipes niemals enden und mehrmals verbunden und getrennt werden können:open(pipe, O_RDWR | O_NONBLOCK);- Hauptschleife:
poll()fürPOLLINEreignisse, möglicherweise auf mehreren Pipes gleichzeitig.read()so viele Daten wie nötig, möglicherweise Schleife aufread()Anrufe.- Wenn
read() == -1underrno == EAGAIN, gehen Sie zurück zupoll()Schritt. - Wenn
read() == -1underrno == EINTR,read()immer wieder. - Wenn
read() == 0, etwas stimmt nicht – es sollte nicht mitO_RDWRpassieren auf Named Pipes, aber nur mitO_RDONLYoder unbenannte Rohre; es zeigt ein geschlossenes Rohr an, das geschlossen und wieder geöffnet werden muss. Wenn Sie benannte und unbenannte Pipes im selbenpoll()mischen Event-Handling-Schleife, dieser Fall muss möglicherweise noch behandelt werden.
- Wenn