Bashでパイプを使用したばかりのときは、これについてはあまり考えませんでした。しかし、システムコールpipe()とfork()を使用してCコードの例を読んだとき、匿名パイプと名前付きパイプの両方を含むパイプを理解する方法を知りたいと思います。
「Linux/Unixのすべてがファイルである」とよく聞かれます。パイプが実際にファイルであり、接続する1つの部分がパイプファイルに書き込み、他の部分がパイプファイルから読み取るようになっているのでしょうか。はいの場合、匿名パイプのパイプファイルはどこに作成されますか?/tmp、/ dev、または...?
ただし、名前付きパイプの例から、おそらくパイプの実装に関係するファイルがないため、パイプを使用すると一時ファイルを明示的に使用するよりもスペースと時間のパフォーマンスが優れていることもわかりました。また、パイプはファイルのようにデータを格納しないようです。だから私はパイプが実際にファイルであることを疑います。
パフォーマンスの質問については、ディスクが不要なためパイプはファイルよりも効率的ですIO=です。したがって、cmd1 | cmd2
はcmd1 > tmpfile; cmd2 < tmpfile
よりも効率的です(これはtmpfile
はRAMディスクまたはその他のメモリデバイスに名前付きパイプとしてバックアップされますが、名前付きパイプの場合、cmd1
は出力としてバックグラウンドで実行する必要がありますパイプがいっぱいになった場合にブロックできます。cmd1
の結果が必要で、その出力をcmd2
に送信する必要がある場合は、cmd1 | tee tmpfile | cmd2
を実行して、cmd1
とcmd2
は、cmd2
からのディスク読み取り操作を回避して並行して実行します。
名前付きパイプは、多くのプロセスが同じパイプに対して読み取り/書き込みを行う場合に役立ちます。これらは、プログラムがそのIO使用する必要があるfilesにstdin/stdoutを使用するように設計されていない場合にも役立ちます。名前付きパイプがファイルシステムエントリ(参照用)がある場合でも、メモリに常駐し、固定バッファサイズを持つストレージの観点から正確にファイル。その他things in UNIXにはファイルではないファイルシステムエントリがあります。/dev/null
または/dev
または/proc
の他のエントリを考えてください。
パイプ(名前付きと名前なし)のバッファーサイズは固定されているため、パイプへの読み取り/書き込み操作がブロックされ、読み取り/書き込みプロセスがIOWait状態になる可能性があります。また、メモリバッファーからの読み取り時にEOF=を受け取るのはいつですか?この動作に関するルールは明確に定義されており、男性にも見られます。
パイプ(名前付きと名前なし)で実行できないことの1つは、データをシークバックすることです。それらはメモリバッファを使用して実装されるため、これは理解できます。
"everything in Linux/Unix is a file"
については、同意しません。名前付きパイプにはファイルシステムエントリがありますが、正確にはファイルではありません。名前のないパイプにはファイルシステムエントリがありません(/proc
を除く)。ただし、ほとんどのIO操作は、名前なしパイプ(およびソケット)を含むファイル記述子を必要とする読み取り/書き込み関数を使用して行われます。 "everything in Linux/Unix is a file"
と言えますが、"most IO in Linux/Unix is done using a file descriptor"
と言えます。
UNIX哲学の2つの基本的な基本は
すべてのプログラムの出力が別のプログラムの入力になることを期待します。
まだ不明です、プログラム。
パイプを使用すると、これら2つの設計の効果を活用できます
ファンダメンタルズを使用して、非常に強力なコマンドチェーンを作成し、目的の結果を得ることができます。
ファイルを操作するほとんどのコマンドラインプログラムは、標準入力(キーボードからの入力)への入力と標準出力(印刷
画面)。
一部のコマンドは、パイプ内でのみ動作するように設計されており、ファイルを直接操作することはできません。
たとえばtr
コマンド
_ls -C | tr 'a-z' 'A-Z'
_
_ cmd1 | cmd2
_
画面ではなく、cmd1のSTDOUTをcmd2のSTDINに送信します。
STDERRはパイプ間で転送されません。
つまり、Pipes is character (|)
はコマンドを接続できます。
STDOUTに書き込むコマンドはすべて、パイプの左側で使用できます。
_ ls - /etc | less
_
STDINから読み取るコマンドはすべて、パイプの右側で使用できます。
_ echo "test print" | lpr
_
従来のパイプは匿名で存在し、プロセスが実行されている間のみ存続するため、「名前なし」です。名前付きパイプはシステムに永続的であり、プロセスの存続期間を超えて存在し、使用されなくなったら削除する必要があります。プロセスは通常、名前付きパイプ(通常はファイルとして表示されます)に接続して、プロセス間通信(IPC)を実行します。
他の答えを補足するには...
stdinとstdoutはファイル記述子であり、ファイルであるかのように読み書きされます。したがって、echo hi | grep hi
、それはechoのstdoutをパイプに置き換え、grepのstdinをこのパイプの他の端に置き換えます。
フレーズを文字通りに解釈しすぎると、「ファイルだけがあり、他には何もない」という意味になります。これは正しい解釈ではありません。
「すべてがファイルである」と言っても、すべてがディスクに保存されているとは限りません。すべてがファイルのように見え、読み取り、書き込みができると言っています。
Unixでは、ファイルまたは非ファイルを開くと、ファイルのように扱うことができます。ただし、すべてのファイルがすべての操作をサポートするわけではありません。例えば。一部のファイル(ファイルではない)はシークをサポートしていません。それらは順番に読み取り/書き込みを行う必要があります(これはパイプとソケットに当てはまります)。
/proc/self/fd/…
をご覧ください/dev/tcp
を参照cat </dev/tcp/towel.blinkenlights.nl/23