パイプを理解する方法


21

bashでパイプを使用したとき、これについてはあまり考えませんでした。しかし、システムコールpipe()とfork()を使用してCコードの例を読むと、匿名パイプと名前付きパイプの両方を含むパイプをどのように理解するのか疑問に思います。

「Linux / Unixのすべてがファイルである」とよく言われます。パイプは実際にはファイルであるため、接続する部分の1つはパイプファイルに書き込み、他の部分はパイプファイルから読み取るのでしょうか。はいの場合、匿名パイプのパイプファイルはどこに作成されますか?/ tmp、/ dev、または...?

ただし、名前付きパイプの例から、パイプを使用すると、一時ファイルを明示的に使用するよりもスペースと時間のパフォーマンスが優れていることがわかりました。また、パイプはファイルのようにデータを保存しないようです。したがって、パイプは実際にはファイルであるとは思えません。

回答:


23

パフォーマンスの質問については、ディスクIOが必要ないため、パイプはファイルよりも効率的です。したがってcmd1 | cmd2、より効率的ですcmd1 > tmpfile; cmd2 < tmpfiletmpfile名前付きパイプとしてRAMディスクまたは他のメモリデバイスにバックアップされている場合、これは当てはまらない可能性がありますが、名前付きパイプのcmd1場合、パイプがいっぱいになると出力がブロックされる可能性があるため、バックグラウンドで実行する必要があります)。の結果が必要であり、cmd1まだ出力を送信cmd2する必要がcmd1 | tee tmpfile | cmd2ある場合は、からのディスク読み取り操作を回避して、並列で実行cmd1およびcmd2実行できるようにする必要がありますcmd2

名前付きパイプは、多くのプロセスが同じパイプに対して読み取り/書き込みを行う場合に役立ちます。また、ファイルを使用する必要があるIOにstdin / stdoutを使用するようにプログラムが設計されていない場合にも役立ちます。名前付きパイプは、メモリに常駐し、ファイルシステムエントリ(参照目的)がある場合でも、固定バッファサイズを持っているため、ストレージの観点では正確にファイルではないため、ファイルを斜体にします。その他のもの UNIXでファイルされることなく、ファイルシステムのエントリを持っている:だけを考え/dev/nullたり、他のエントリに/dev/proc

パイプ(名前付きおよび名前なし)のバッファサイズは固定されているため、それらに対する読み取り/書き込み操作がブロックされ、読み取り/書き込みプロセスがIOWait状態になります。また、メモリバッファから読み取るときにEOFを受信するのはいつですか?この動作に関するルールは明確に定義されており、男性に記載されています。

パイプ(名前付きおよび名前なし)でできないことの1つは、データをシークバックすることです。メモリバッファを使用して実装されているため、これは理解できます。

について"everything in Linux/Unix is a file"、私は同意しません。名前付きパイプにはファイルシステムエントリがありますが、正確にはファイルではありません。名前のないパイプにはファイルシステムエントリがありません(多分を除く/proc)。ただし、UNIXでのほとんどのIO操作は、名前なしパイプ(およびソケット)を含むファイル記述子を必要とする読み取り/書き込み機能を使用して行われます。私たちはそう言うことができるとは思いません"everything in Linux/Unix is a file"が、確かにそう言うことができ"most IO in Linux/Unix is done using a file descriptor"ます。


ありがとう!2つのコマンドは、最初の終了後に2番目のコマンドが実行されるのではなく、並行して実行されるパイプで接続されていますか?
ティム

はい、2つのコマンドは並行して実行されます。そうでなく、最初の出力がバッファよりも大きい場合、ブロックされます。2つの異なるシェルで実行しcmd1 > fifocmd2 < fifoで名前付きパイプを作成して試してみることができmkfifo fifoます。
-jfg956

別のテストとして、実行cmd2中に強制終了することもできます。おそらく、破損したパイプメッセージの報告を停止します。cmd1cmd1
-jfg956

ありがとう!ブロックされるとはどういう意味ですか?これが発生した場合、ブロック後のストリーム内の日付は失われますか?
ティム

2
データは失われません。パイプバッファーがいっぱいの場合、パイプcmd1へのの書き込みは、パイプcmd2からデータを読み取ったときにのみ戻ります。同様にcmd2、バッファが空の場合cmd1、パイプへの書き込みまで、パイプからの読み取りはブロックされます。
jfg956

4

UNIX哲学の2つの基本的な基礎は次のとおりです。

  1. 一つのことをうまく行う小さなプログラムを作成する。
  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)を実行します。

ソース:http : //en.wikipedia.org/wiki/Named_pipe


3

他の回答を補足するには...

stdinとstdoutはファイル記述子であり、ファイルであるかのように読み書きされます。したがって、を行うことができecho hi | grep hi、エコーのstdoutをパイプに置き換え、grepのstdinをこのパイプのもう一方の端に置き換えます。


1

すべてがファイルです。

フレーズを文字通りに解釈しすぎると、「ファイルのみがあり、他には何もない」という意味になります。これは正しい解釈ではありません。

「すべてがファイルである」と言うとき、すべてがディスクに保存されていると言っているのではありません。私たちは、すべてがファイルのように見え、読むことができ、書き込むことができると言っています。

Unixでは、ファイルまたは非ファイルが開かれると、ファイルのように扱うことができます。ただし、すべてのファイルがすべての操作をサポートしているわけではありません。たとえば、一部のファイル(ファイルではない)はシークをサポートしていません。これらは順番に読み取り/書き込みする必要があります(これはパイプとソケットに当てはまります)。

すべてにファイル名があります(一部のシステム:Debian Gnu / Linux、および他の多くのGnu / Linuxなど)。

  • 開いているすべてのファイルにはファイル名が付けられます。見る/proc/self/fd/…
  • ネットワークソケットは、ファイル名を参照して開くことができます/dev/tcp
    たとえば、cat </dev/tcp/towel.blinkenlights.nl/23

その最後の部分は、/procファイルシステムを備えたシステム、および/dev/tcpファイル構造を提供するシステム(またはシェル)でのみ有効です。
クサラナンダ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.