Wie führe ich ein nicht blockierendes fopen auf einer benannten Pipe (mkfifo) durch?

Lesezeit: 3 Minuten

Benutzer-Avatar
Zxaos

Wenn ich ein Programm habe, das eine benannte Pipe mit mkfifo erstellt und zu öffnen versucht, wie kann ich eine Pipe zum Lesen oder Schreiben öffnen, ohne sie zu blockieren?

Insbesondere schreibe ich ein C-Programm, das mit oder ohne GUI (in Java geschrieben) ausgeführt werden kann.

Im C-Programm erstelle ich erfolgreich die benannten Pipes mit mkfifo, aber wenn ich das tue

FILE* in = fopen(PIPE_IN, "r"); /* Where PIPE_IN is the filename*/

fopen kehrt erst zurück, wenn die GUI diese Pipe zum Schreiben öffnet. Was ich tun möchte, ist, dass diese Pipe einmal gelesen werden kann (falls) die GUI beschließt, darauf zu schreiben – ich werde den Dateideskriptor in einen Aufruf von select() einfügen. Es ist vernünftig zu erwarten, dass die Java-GUI möglicherweise nie wirklich gestartet wird, daher kann ich mich nicht darauf verlassen, dass sie das andere Ende der Pipe an einem bestimmten Punkt oder überhaupt öffnet.

Ich werde auch ein zweites Rohr zum Schreiben offen haben, und ich gehe davon aus, dass ich das gleiche Problem haben werde. Außerdem kann ich O_NONBLOCK nicht auf eine Ausgabepipe setzen, die keinen Reader hat.

Irgendwelche Vorschläge?

(Dies läuft auf einem Linux-System)

  • Müssen Sie die Ausgangsleitung öffnen, bevor select() auf die Eingangsleitung feuert?

    – Tim Post

    24. Februar 2009 um 3:47 Uhr

  • @tinkertim – Ich nehme an, technisch gesehen nicht – ich hatte beide in einer Setup-Funktion eingerichtet, aber ich konnte einfach zuerst die Ausgangsleitung einrichten und dann select aufrufen, warum?

    – Zxaos

    24. Februar 2009 um 4:47 Uhr

Benutzer-Avatar
jpalecek

Sie könnten open() dein Rohr O_RDONLY | O_NONBLOCKund wenn Sie den C-Stream möchten, können Sie ihn mit bekommen fdopen(). Es könnte jedoch ein Problem mit der geben select() – AFAIK, eine zum Lesen geöffnete Pfeife, die keinen Schreiber hat, ist immer zum Lesen bereit, und read() gibt 0 zurück, also die select() würde auf unbestimmte Zeit feuern.

Ein klumpiger Weg, dies zu überwinden, wäre, das Rohr zu öffnen O_RDWR; das heißt, Sie müssen mindestens einen Writer haben (Ihr C++-Programm). Was dein Problem sowieso lösen würde.

  • Ich werde das für den Leser versuchen – aber ich kann O_NONBLOCK nicht auf eine Ausgangsleitung setzen …

    – Zxaos

    24. Februar 2009 um 3:43 Uhr

  • Der POSIX-Standard sagt (von select()): “Ein Deskriptor soll als bereit zum Lesen betrachtet werden, wenn ein Aufruf einer Eingabefunktion mit O_NONBLOCK clear nicht blockieren würde, unabhängig davon, ob die Funktion erfolgreich Daten übertragen würde oder nicht.” (POSIX.1:2008).

    – Jonathan Leffler

    24. Februar 2009 um 4:13 Uhr

  • Das Öffnen der Pipe O_RDWR würde beim Lesen (oder Schreiben) des Programms zu einem Deadlock führen – es sei denn, es gibt tatsächlich einen anderen Prozess, der auch die Pipe geöffnet hat.

    – Jonathan Leffler

    24. Februar 2009 um 4:15 Uhr

  • @Jonathan Leffler – Aber könnte ich es RDWR öffnen und es einfach abfragen, um zu sehen, wann ein anderer Prozess tatsächlich darauf geschrieben hat? Das sollte nicht zu Deadlocks führen, oder?

    – Zxaos

    24. Februar 2009 um 4:46 Uhr

  • Ja, und dies sollte in select() blockieren. Keine solchen Lösungen für das schreibende Ende einer Pipe, wahrscheinlich ist das Beste, was Sie tun könnten, das schreibende Ende zu öffnen, nachdem Sie eine Eingabeaufforderung vom Java-Programm erhalten haben

    – jpalecek

    24. Februar 2009 um 9:41 Uhr

1265360cookie-checkWie führe ich ein nicht blockierendes fopen auf einer benannten Pipe (mkfifo) durch?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy