パイプシェルプログラムは、出力/入力速度のバランスをどのように維持しますか? [コピー]

パイプシェルプログラムは、出力/入力速度のバランスをどのように維持しますか? [コピー]

重複の可能性:
whileループをバッシングしてパイプから読み込みます。

私はWebプログラミングの背景知識があり、ローカルシェルの機能を使用することに興味があります。私が知っている限り、プログラムがファイルを読むときに必要な速度で読み取ることができます。しかし、プログラムがパイプを介して他のプログラムから入力を受け取り、それをリアルタイムで処理できない場合、どのように機能するのか疑問に思います。

良い例はビデオエンコーディングです。デコーダがビデオファイルを指し、その出力がエンコーダの入力にパイプされるとしましょう。デコードされた画像の合計サイズがメモリ+スワップ空間を超えるため、完全にバッファリングする方法はないようです。私はstdinとstdoutの読み取りと書き込みの呼び出しを見つけましたが、この例のエンコーダがすべてのデータを同時に処理できないときに実際に何が起こるのかを知りたいです。どういうわけかデコーダに必要な速度を教えてください。そのような信号に対してデコーダプログラムを特別に準備し、それに応じて処理速度を変更する必要がありますか?そうでなければ、最終的にバランスをとる方法は何ですか?

答え1

ライターがパイプに書き込んでパイプがいっぱいになると(サイズは数キロバイトに制限されています)、リーダーの1つがスペースを解放するまでそのプロセスはブロックされます。同様に、リーダーがパイプからデータを読み取ると、そのプロセスは何かがあるまでブロックされます。

プログラマーがこれらの読み取りおよび書き込みをキューに追加するために使用できる非同期書き込みおよび読み取りもあります。

私は読書を強くお勧めしますBeejのご案内、Beejから始まるUnix プロセス間通信ガイド

2つのパラメータを使用してそれを呼び出します。最初は作成者の睡眠時間、2番目は読者の睡眠時間です。 argsを試してください0 33 0

#!/bin/sh
write_sleep=$1
read_sleep=$2
writer(){
  echo writing output >&2
  echo hi
  sleep $write_sleep
  echo writing output >&2
  echo hi
  sleep $write_sleep
  echo writing output >&2
  echo hi
  sleep $write_sleep
}
reader(){
  while true; do
    echo getting input >&2
    read input
    [ $input ] || { echo input is empty >&2 &&  break; }
    echo $input
    sleep $read_sleep
  done
}

writer | reader

答え2

パイプはプログラミングレベルの一般的なUNIX記述子です。パイプを介して通信するために2つのプログラムを設定するときに最初に表示されるのは、対話する標準出力と標準入力記述子です。なぜなら、シェルは実際にそのように設定するからです。このように設定すると、これらの記述子はいくつかの特別な特性を持ちますが、プロセスは他のファイル記述子と同様に記述子と対話します(これはUNIXの哲学全体です)。

デフォルトでは、書き込みプロセスはパイプにデータを書き込むことができますが、パイプには最大保存制限(バッファ)があるため、パイプがいっぱいになるとブロックされたり、要求が「Try」で応答される可能性があります。作成者がブロックされたくないので、後でもう一度やり直してください。」

代わりに、読者は好きなだけ読むことができますが、パイプが空の場合はブロックされる可能性があります(または「後でもう一度やり直してください」と答える可能性があります)。

関連情報