私は使用してファイル記述子を作成しました
mkfifo fifo
このパイプに何かが書き込まれたらすぐに再利用したい(immediately)。使うべきか
tail -f fifo
または
while true; do cat fifo; done
?
彼らは同じことをしているようで、私はパフォーマンスの違いを測定できませんでした。ただし、システムがinotify(Busyboxなど)をサポートしていない場合、前者は
tail -f -s 0 fifo
しかし、これはCPUを100%使用します(テストしてください:mkfifo fifo && busybox tail -f -s 0 fifo & echo hi>fifo
/fg 1
でキャンセルして、 CtrlC)。それでは、while-true-catの方が信頼性の高いソリューションですか?
あなたがするとき:
_cat fifo
_
他のプロセスがfifo
をまだ書き込み用に開いていない場合、cat
はopen()
システムコールをブロックします。別のプロセスが書き込み用にファイルを開くと、パイプがインスタンス化され、open()
が返されます。 cat
はread()
をループで呼び出し、read()
は他のプロセスがパイプにデータを書き込むまでブロックします。
cat
は、他のすべての書き込みプロセスがファイル記述子をfifo
にクローズしたときに、ファイルの終わり(eof)を参照します。その時点でcat
は終了し、パイプは破棄されます¹。
その後、cat
を実行して、fifo
に書き込まれる内容を読み取る必要があります(ただし、別のパイプインスタンスを介して)。
に:
_tail -f file
_
cat
と同様に、tail
は、プロセスが書き込み用にファイルを開くのを待ちます。しかし、ここでは、最初からコピーする_-n +1
_を指定しなかったため、tail
は、最後の10行が何であるかを確認するためにeofまで待機する必要があるため、書き込みが終了するまで何も表示されません。閉まっている。
その後、tail
はパイプへのfdを閉じません。つまり、パイプインスタンスは破棄されず、毎秒パイプからの読み取りを試行します(Linuxでは、inotify
を使用してポーリングを回避できます。 GNU tail
do that there)。そのread()
はeof(すぐに戻る)を返すため、_-s 0
_(100 GNU tail
は、他のプロセスがファイルを再度書き込み用に開くまで、1秒待つ代わりにread()
sの間で待機しないことを意味します).
ここでは代わりに、cat
を使用することをお勧めしますが、パイプインスタンスがインスタンス化された後は常にパイプインスタンスがそのまま残るようにしてください。そのため、ほとんどのシステムでは、次のことができます。
_cat 0<> fifo # the 0 is needed for recent versions of ksh93 where the
# default fd changed from 0 to 1 for the <> operator
_
cat
のstdinは読み取りと書き込みの両方で開かれます。つまり、cat
はeofを決して見ません(書き込みのためにfifo
を開く他のプロセスがない場合でも、すぐにパイプをインスタンス化します)。
それが機能しないシステムでは、代わりに次のようにすることができます:
_cat < fifo 3> fifo
_
このように、他のプロセスがfifo
を書き込み用に開くとすぐに、最初の読み取り専用open()
が返されます。この時点で、シェルは開始前に書き込み専用open()
を実行しますcat
。パイプが再び破壊されるのを防ぎます。
まとめると、
cat file
_と比較すると、最初のラウンドの後で停止しません。tail -n +1 -f file
_と比較して:最初のラウンドの後、毎秒役に立たないread()
を実行しません。パイプの1つのインスタンスでeofが発生することはなく、最大1秒は発生しません。最初のプロセスがパイプを閉じた後、2番目のプロセスが書き込み用にパイプを開いたときの遅延。tail -f file
_と比較されます。上記に加えて、何かを出力する前に最初のラウンドが終了するのを待つ必要はありません(最後の10行のみ)。cat file
_と比較すると、パイプインスタンスは1つしかありません。 ¹で言及されているレースウィンドウは回避されます。thisこの時点で、eofを示す最後のread()
とcat
がパイプの読み取り終了を終了して閉じる間に、実際にはプロセスがfifo
を開いて再度書き込むために(およびまだ読み終わりがあるのでブロックされません)。次に、cat
が終了した後、別のプロセスがfifo
を読み取り用に開く前に何かを書き込むと、SIGPIPEで強制終了されます。
別の解決策を提案させてください。パイプは、いくつかのプロセスが2番目の端に書き込む限り、読み取りに使用できます。したがって、バックグラウンド(または別の端末)で偽のcat
を作成できます。たとえば、次のようにします。
mkfifo fifo
cat >fifo &
cat fifo
今、あなたは好きなだけFIFOに書き込むことができ、終了したら現在のcat
を殺すだけで C-c、次にfg
を使用して、最初にcat
をバックグラウンドから取得し、最後に C-d それを止める。