Hierfür können Sie ein FIFO verwenden, das mit erstellt wurde mkfifo
. Beachten Sie jedoch, dass es sehr leicht ist, versehentlich einen Deadlock zu erstellen. Lassen Sie mich das erklären - nehmen Sie Ihr hypothetisches "kreisförmiges" Beispiel. Sie führen die Ausgabe eines Befehls seiner Eingabe zu. Es gibt mindestens zwei Möglichkeiten, wie dies zum Stillstand kommen kann:
Der Befehl hat einen Ausgabepuffer. Es ist teilweise gefüllt, wurde aber noch nicht gelöscht (tatsächlich geschrieben). Sobald es voll ist, wird es es tun. Es wird also wieder die Eingabe gelesen. Es bleibt für immer dort, denn die Eingabe, auf die es wartet, befindet sich tatsächlich im Ausgabepuffer. Und es wird nicht geleert, bis es diese Eingabe bekommt ...
Der Befehl hat eine Reihe von Ausgaben zu schreiben. Es beginnt mit dem Schreiben, aber der Kernel-Pipe-Puffer füllt sich. Also sitzt es da und wartet darauf, dass sie Platz im Puffer haben. Das wird passieren, sobald es seine Eingabe liest, dh niemals, weil es das nicht tun wird, bis es fertig ist, was auch immer an seine Ausgabe geschrieben wird.
Das heißt, hier ist, wie Sie es tun. Dieses Beispiel ist mit od
, um eine endlose Kette von Hex-Dumps zu erstellen:
mkfifo fifo
( echo "we need enough to make it actually write a line out"; cat fifo ) \
| stdbuf -i0 -o0 -- od -t x1 | tee fifo
Beachten Sie, dass schließlich aufhört. Warum? Es kam zum Stillstand, Nr. 2 oben. Möglicherweise bemerken Sie dort auch den stdbuf
Aufruf, um die Pufferung zu deaktivieren. Ohne es? Deadlocks ohne Ausgabe.
Im Allgemeinen würde ich ein Makefile (Befehl make) verwenden und versuchen, Ihr Diagramm Makefile-Regeln zuzuordnen.
Um sich wiederholende / zyklische Befehle zu haben, müssen wir eine Iterationsrichtlinie definieren. Mit:
Jedes
make
wird jeweils eine Iteration erzeugen.quelle
make
, aber unnötig: Wenn Sie eine Zwischendatei verwenden, warum nicht einfach eine Schleife verwenden, um sie zu verwalten?make
geht um Makros, die hier eine perfekte Anwendung sind.Wissen Sie, ich bin nicht davon überzeugt, dass Sie unbedingt eine sich wiederholende Rückkopplungsschleife benötigen, wenn Ihre Diagramme dargestellt werden. Vielleicht können Sie sogar eine dauerhafte Pipeline zwischen Koprozessen verwenden . Andererseits kann es sein, dass es keinen allzu großen Unterschied gibt - sobald Sie eine Zeile in einem Coprozess öffnen, können Sie typische Stilschleifen implementieren, in die nur Informationen geschrieben und daraus gelesen werden, ohne dass etwas ganz Besonderes getan wird.
Zunächst scheint es, dass dies
bc
für Sie ein Hauptkandidat für einen Koprozess ist. In könnenbc
Siedefine
Funktionen, die so ziemlich das tun können, was Sie in Ihrem Pseudocode verlangen. Zum Beispiel könnten einige sehr einfache Funktionen dazu so aussehen:... was würde drucken ...
Aber natürlich tut es nicht zuletzt . Sobald die für die Pipe zuständige Unterschale
printf
beendet wird (direkt nach demprintf
Schreibena()\n
in die Pipe), wird die Pipe abgerissen undbc
die Eingabe wird geschlossen und sie wird ebenfalls beendet. Das ist bei weitem nicht so nützlich, wie es sein könnte.@derobert hat bereits erwähnten FIFO s , wie sie durch die Schaffung eines gehabt werden Named Pipe mit der Datei -
mkfifo
Dienstprogramm. Dies sind im Wesentlichen auch nur Pipes, mit der Ausnahme, dass der Systemkern einen Dateisystemeintrag mit beiden Enden verbindet. Diese sind sehr nützlich, aber es wäre schöner, wenn Sie nur eine Pipe hätten, ohne zu riskieren, dass sie im Dateisystem beschnüffelt wird.Wie es passiert, macht Ihre Shell dies oft. Wenn Sie eine Shell verwenden, die die Prozessersetzung implementiert , haben Sie ein sehr einfaches Mittel, um eine dauerhafte Pipe zu erhalten - die Art, die Sie möglicherweise einem Hintergrundprozess zuweisen, mit dem Sie kommunizieren können.
In
bash
zum Beispiel können Sie sehen , wie die Prozess Substitution Werke:Sie sehen, es ist wirklich eine Substitution . Die Shell ersetzt während der Expansion einen Wert, der dem Pfad zu einer Verbindung zu einer Pipe entspricht . Sie können das ausnutzen - Sie müssen nicht gezwungen sein, diese Pipe nur zu verwenden, um mit dem Prozess zu kommunizieren, der in der
()
Substitution selbst abläuft ...... was druckt ...
Jetzt weiß ich, dass verschiedene Shells das Coprozess- Ding auf unterschiedliche Weise ausführen - und dass es eine bestimmte Syntax
bash
für das Einrichten eines (und wahrscheinlich auch einerzsh
) gibt -, aber ich weiß nicht, wie diese Dinge funktionieren. Ich weiß nur, dass Sie die obige Syntax verwenden können, um praktisch dasselbe zu tun, ohne das Rigmarole in beidenbash
undzsh
- und Sie können eine sehr ähnliche Sache in hier-Dokumenten tundash
undbusybox ash
den gleichen Zweck mit hier-Dokumenten erreichen (weildash
undbusybox
hier- Dokumente mit Pipes anstelle von temporären Dateien (wie die beiden anderen) .Also, wenn angewendet auf
bc
...... das ist der schwierige Teil. Und das ist der lustige Teil ...
... was druckt ...
... und es läuft noch ...
... was mir nur den letzten Wert für
bc
's gibt,a
anstatt diea()
Funktion aufzurufen , um ihn zu erhöhen und zu drucken ...Es wird in der Tat so lange weiterlaufen, bis ich es töte und seine IPC-Rohre abreiße ...
quelle
eval "exec {BCOUT}<>"<(:) "{BCIN}<>"<(:)
funktioniert dies auch