以下を使用してファイル記述子を作成しました。
mkfifo fifo
このパイプに何かが書かれたら、再利用したいです。まもなく。私は使うべきですか?
tail -f fifo
または
while true; do cat fifo; done
?
彼らは同じことをしているようで、パフォーマンスの違いを測定することはできません。ただし、システムがinotify(Busyboxなど)をサポートしていない場合は、前者を次のように設定する必要があります。
tail -f -s 0 fifo
mkfifo fifo && busybox tail -f -s 0 fifo & echo hi>fifo
ただし、これはCPU使用率が100%です(/cancelfg 1
およびでテストCtrlC)。もしそうなら、while-true-catはより信頼性の高いソリューションですか?
答え1
これを行うとき:
cat fifo
fifo
すでに書き込み用に開いている他のプロセスがないと仮定すると、システムコールがcat
ブロックされますopen()
。他のプロセスが書き込み用にファイルを開くと、パイプはインスタンス化されてopen()
返されます。ループが呼び出され、他のプロセスがパイプにデータを書き込むまでブロックされますcat
。read()
read()
cat
ファイル終了文字は、他のすべての書き込みプロセスがファイル記述子を閉じたときに表示されますfifo
。これがcat
終了し、パイプラインが破壊されます。
cat
後で作成した内容を読み取るには、もう一度実行する必要がありますfifo
(ただし、他のパイプインスタンスを介して)。
存在する:
tail -f file
同様に、プロセスが書き込み用にファイルを開くのを待ちますcat
。ところで、ここでは最初からコピーをtail
指定しなかったので、最後の10行が何かを調べるにはeofまで待たなければならないため、書き込みが終わるまで何も見えません。-n +1
tail
その後、tail
対応するfdはパイプに対して閉じられません。これは、パイプインスタンスが破壊されず、毎秒パイプから読み取ろうとすることを意味します(Linuxでは、inotify
一部のバージョンのGNUを使用してポーリングを防ぐことができますtail
)。これは、他のプロセスが書き換えるためにファイルを開くまでeof(即時100%CPUが表示される理由です(GNUの場合は1秒待つのではなくs間を待たないことを意味します))read()
を返します。-s 0
tail
read()
代わりにここでを使用したいかもしれませんが、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がなく、2番目のプロセスが書き込み用にパイプを開かなかった後に遅延があります。最大1秒。最初はそれを閉じました。 - と比較して
tail -f file
。上記に加えて、何かを出力する前に最初のラウンドが終わるまで待つ必要はありません(最後の10行のみ)。 - ループとは異なり、
cat file
パイプインスタンスは1つだけです。 1で述べた競合ウィンドウは防止されます。
read()
1この時点で、eofの最後の表現とcat
パイプの読み取りの終わりが終了して閉じるまでの間に、実際にプロセスが書き込みのfifo
ためにパイプを再度開くことができる小さなウィンドウがあります。まだ読んだ内容があります。 Take the end).その後cat
、終了後に他のプロセスが読み取りプロセスを開く前にfifo
何かを書くと、SIGPIPEによって終了します。
答え2
別の解決策を提案します。 2番目の最後に書き込むプロセスがある限り、パイプを読み取ることができます。したがって、cat
バックグラウンド(または他の端末)から偽を作成できます。たとえば、次のようになります。
mkfifo fifo
cat >fifo &
cat fifo
これで必要に応じてfifoに書き込むことができ、完了したら現在のプロセス終了を使用してcat
からC-c最初にバックグラウンドで開始fg
し、最後に停止します。cat
C-d