web-dev-qa-db-ja.com

FIFOパイプを閉じるにはどうすればよいですか?

このスクリプト:

#!/bin/bash
tmppipe=/tmp/temppipe
mkfifo $tmppipe
echo "test" > $tmppipe
cat $tmppipe
exit

終了しません。 catコマンドがパイプからEOFを待機していると想定しています。どのように送信するのですか?

6
Benubird

いいえ、そうです

_echo test > "$tmppipe" # BTW, you've got the quotes in the wrong places
_

それがハングします。より正確には、シェルはechoを実行する前に書き込み用のパイプを開くシェルです。

pipeはプロセス間通信メカニズムであり、同時にを実行しているプロセス間で使用されます。ここで、open(WR_ONLY)(_>_)は、別のプロセスが読み取りモードでopenを実行するまでブロックされます。

_echo test > "$tmppipe" &
cat < "$tmppipe"
_

echocatが同時に実行されるため、機能します。

Linuxでは、次の方法で回避できます。

_exec 3<> "$tmppipe"
echo test >&3
cat < "$tmppipe"
exec 3<&-
_

これは、パイプでの読み取りと書き込みopens(_<>_)がLinuxではブロックされないため、およびechoによる_test\n_出力がパイプに収まるほど小さいため、書き込みと順次読み取り。

次のようなより大きな出力では機能しません。

_exec 3<> "$tmppipe"
seq 100000 >&3
cat < "$tmppipe"
exec 3<&-
_

seqはパイプ(現在のバージョンのLinuxでは64kiB)を満たし、他のプロセスがそのパイプからデータを読み取るまでブロックするため、catseqが完了するまで実行されないため、これは起こりません。

ご了承ください:

_echo test 1<> "$tmppipe"
cat < "$tmppipe"
_

echoコマンドラインがパイプを開き、テストを書き込んでからパイプを閉じるため、ファイル記述子が開かれていないため、システムはパイプを破棄します。したがって、次のcatコマンドラインは、新しいパイプをインスタンス化しようとします(書き込みのためにfifoファイルが開かれるまでブロックします)。

7

答えは明白です-パイプはechoによってロックされており、猫には届きません!

パイプはデータを格納しません。プロセスがパイプに書き込もうとすると、パイプのもう一方の端に何かが接続されて読み取られるまで、書き込みを完了できません。

この特定の例を解決する方法は、使用することです

echo "test" > $tmppipe &

書き込みプロセスをバックグラウンドで実行します。このようにして、スクリプトが続行している間、catに到達して完了するまで待機します。

0
Benubird