リダイレクトループの作成方法

リダイレクトループの作成方法

これは主に学術的な理由によるものです。 ;-)

次のBash文を考えてみましょう。

foo | bar

これは両方のプロセスを実行しfoobar標準出力がfoo標準入力に接続されるようにしますbar。今まではそんなに良くなった。

私たちが呼び出すことができるfooメソッドはありますか?bar返品反対方向につながっていますか?

foo.stdout -> bar.stdin
foo.stdin  <- bar.stdout

私が理解したように、Bash呼び出しは相互接続されたFDペアを作成し、そのサブプロセスで/をpipe(2)置き換えるために使用できます。カーネルレベルでは2回呼び出すことができない理由はなく、上記の循環配列を配置します。stdinstdoutpipe(2)

しかし、実際にはシェル構文を理解することはできません。するそれ。

これまで私が思い出すことができる最良のアイデアは、名前付きパイプを使用するか、サブシェルを起動し、何とかクレイジーFDからFDにリダイレクトすることです。

ベストアンサー1

Bashでは、次のものを使用できます。共生(bashは複数のcoprocを正しくサポートしていませんが、ここでは1つだけが必要です):

#!/bin/bash
set -e
coproc { while read -r line; do echo "$BASHPID read: $line";  done; }
i=0; while :; do
    echo "$BASHPID writing>> $i"
    echo $i >&"${COPROC[1]}"
    read -r line <&"${COPROC[0]}"
    echo "$BASHPID coproc produced>> $line"
    i=$((i+1))
done

または名前付きパイプ(単純なPOSIXシェルでも機能します):

#!/bin/bash
set -e
trap 'rm -rf "$tmpd"' EXIT
tmpd=$(mktemp -d)

mkfifo "$tmpd/p0" "$tmpd/p1"
exec 3<>"$tmpd/p0"
exec 4<>"$tmpd/p1"
rm -rf "$tmpd"

( while read -r line; do echo "$BASHPID read: $line";  done; ) <&3 >&4  &
i=0; while :; do
    echo "$BASHPID writing>> $i" 
    echo $i >&3
    read -r line <&4
    echo "$BASHPID coproc produced>> $line"
    i=$((i+1))
done 

シェルでfdを扱うことに慣れていない場合は、みんな見えないかもしれません。

また、スケジューリングへのパイプの影響により、空のパイプバッファを持つパイプから読み取るのと同じように、パイプバッファ全体を持つパイプに書き込むとブロックされるため、特定の読み書きパターンが閉じ込められます。二重ロック。

上記の2つの例の出力は次のとおりです。

32435 writing>> 0
32435 coproc produced>> 32441 read: 0
32435 writing>> 1
32435 coproc produced>> 32441 read: 1
32435 writing>> 2
32435 coproc produced>> 32441 read: 2
32435 writing>> 3
32435 coproc produced>> 32441 read: 3
32435 writing>> 4
32435 coproc produced>> 32441 read: 4

おすすめ記事