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 von0
bedeutet EOF - die andere Seite hat ihre Verbindung geschlossen. Dies entspricht (normalerweise, aber nicht auf allen Betriebssystemen)poll()
Rückgabe einesPOLLHUP
revent. Vielleicht möchten Sie nachPOLLHUP
suchen bevor Sieread()
versuchen , ist aber seitread()
nicht zwingend erforderlich gibt garantiert0
zurü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 aufPOLLIN
zu warten Ereignis vor dem Aufruf vonread()
, wartet er darauf, dass der Writer eine Verbindung herstellt, und erzeugt keine EOFs. read()
Rückgabewert-1
bedeutet 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 einenPOLLIN
revent, 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_NONBLOCK
verwendet . 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()
POLLHUP
revent undread()
gibt0
zurü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 einenPOLLIN
aus 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 == EAGAIN
wenn die Verbindung noch offen ist, oder es wird0
zurü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()
POLLHUP
revent undread()
gibt0
zurü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 einenPOLLIN
neu starten, wenn die Daten zum Lesen bereit sind. Für benannte Pipes verursacht EOF jedoch nichtPOLLIN
oderPOLLHUP
Einnahmen.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 == EAGAIN
nicht zurückgegeben , noch wird es0
zurü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 == EINTR
wenn 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 einenPOLLIN
neu starten, wenn die Daten zum Lesen bereit sind. EOF verursacht jedoch nichtPOLLIN
oderPOLLHUP
nutzt Named Pipes.- Nachdem alle aktuell verfügbaren Daten gelesen wurden,
read()
gibt-1
zurü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() == -1
underrno == 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ürPOLLIN
Ereignisse, 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() == -1
underrno == EAGAIN
, gehen Sie zurück zupoll()
Schritt. - Falls
read() == -1
underrno == 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ürPOLLIN
Ereignisse, möglicherweise auf mehreren Pipes gleichzeitig.read()
so viele Daten wie nötig, möglicherweise Schleife aufread()
Anrufe.- Wenn
read() == -1
underrno == EAGAIN
, gehen Sie zurück zupoll()
Schritt. - Wenn
read() == -1
underrno == EINTR
,read()
immer wieder. - Wenn
read() == 0
, etwas stimmt nicht – es sollte nicht mitO_RDWR
passieren auf Named Pipes, aber nur mitO_RDONLY
oder 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