シェルがパイプされたコマンドを実際に実行する方法については、まったく考えたことはありません。パイプについて考える方法として、「あるプログラムのstdoutがpipedを別のプログラムのstdinに取り込む」と常に言われてきました。したがって、当然のことながら、たとえば、A | B
、A
が最初に実行され、次にB
がA
の標準出力を取得して、その標準出力を使用すると考えましたA
を入力として使用します。
しかし、人々がps
で特定のプロセスを検索するとき、grep
が表示されないようにするために、コマンドの最後にgrep -v "grep"
を含めることに気づきました最終出力で。
これは、コマンドps aux | grep "bash" | grep -v "grep"
では、ps
がgrep
が実行中であることを認識していたため、ps
の出力に含まれることを意味します。しかし、出力がps
にパイプされる前にgrep
が実行を終了した場合、grep
が実行中であったことをどのようにして知りましたか?
flamingtoast@FTOAST-UBUNTU: ~$ ps | grep ".*"
PID TTY TIME CMD
3773 pts/0 00:00:00 bash
3784 pts/0 00:00:00 ps
3785 pts/0 00:00:00 grep
パイプコマンドは同時に実行されます。 ps | grep …
を実行する場合、ps
かどうかは、ドローの運(または、シェルの仕組みの詳細と、カーネルの腸の奥深くにあるスケジューラの微調整の問題)です。またはgrep
が最初に開始され、いずれの場合も同時に実行され続けます。
これは、最初のプログラムが操作を完了する前に、最初のプログラムから出力されるデータを2番目のプログラムが処理できるようにするために非常によく使用されます。例えば
grep pattern very-large-file | tr a-z A-Z
grep
が大きなファイルの走査を完了する前であっても、一致する行を大文字で表示し始めます。
grep pattern very-large-file | head -n 1
最初に一致した行を表示し、grep
が入力ファイルの読み取りを完了する前に処理を停止する場合があります。
パイプされたプログラムが順番に実行される場所を読んだ場合は、このドキュメントから逃げてください。パイププログラムは同時に実行され、常に実行されます。
コマンドが実行される順序は実際には重要ではなく、保証されません。シェルは、pipe()
、fork()
、dup()
およびexecve()
の不可解な詳細は別として、最初にデータのパイプであるパイプを作成しますこれはプロセス間を流れ、パイプの端が接続されたプロセスを作成します。実行される最初のプロセスは、2番目のプロセスからの入力の待機をブロックしたり、2番目のプロセスがパイプからのデータの読み取りを開始するのを待機したりします。これらの待機は任意に長くなる可能性があり、問題ではありません。プロセスが実行される順序に関係なく、データは最終的に転送され、すべてが機能します。
死んだ馬を倒すリスクがあるという誤解は、
あ | B
に相当
あ > temporary_fileB < temporary_file rm temporary_file
しかし、Unixが作成され、子供たちが恐竜を学校に乗せたとき、ディスクは非常に小さく、ファイルシステムのすべての空き領域を消費するのは無害なコマンドでした。 B
がgrep some_very_obscure_string
のようなものである場合、パイプラインの最終出力はmuchが中間ファイルよりも小さくなる可能性があります。したがって、パイプは「run [〜#〜] a [〜#〜]の省略形ではなく最初に開発され、次に[〜#〜] b [〜 #〜][〜#〜] a [〜#〜]からの入力があるモデルですが、B
がA
と同時に実行され、保存する必要がないようにする方法としてディスク上の中間ファイル。
通常、これはbashで実行します。プロセスは同時に動作して起動しますが、シェルによって並行して実行されます。どのように可能ですか?
システムは、execの実行速度と指定されたコマンドの開始を保証しません。シェルから独立していますが、システムです。それの訳は:
ps auxww| grep ps | cat
grep
および/またはps
コマンドを一度表示してから、次に表示します。カーネルが実際にシステム実行機能を使用してプロセスを開始する速度に依存します。