stdin
と言った方が正しいでしょう。 、 stdout
、および stderr
ファイルではなく「I/Oストリーム」です。お気づきのように、これらのエンティティはファイル システムに存在しません。しかし、Unix の哲学は、I/O に関する限り、「すべてがファイルである」というものです。実際には、これは同じライブラリ関数とインターフェイスを使用できることを意味します (printf
,scanf
、 read
、 write
、 select
など) I/O ストリームがキーボード、ディスク ファイル、ソケット、パイプ、またはその他の I/O 抽象化に接続されているかどうかを気にする必要はありません。
ほとんどのプログラムは、入力を読み取り、出力を書き込み、エラーをログに記録する必要があるため、 stdin
、 stdout
、および stderr
プログラミングの便宜上、あらかじめ定義されています。これは単なる規則であり、オペレーティング システムによって強制されるものではありません。
残念ながら、あなたの理解は完全に後退しています。 :)
プログラムの「標準入力」、「標準出力」、および「標準エラー」について考えてください。 カーネルの観点からではなく、観点から。
プログラムが出力を印刷する必要がある場合、通常は「標準出力」に印刷します。プログラムは通常、printf
を使用して出力を標準出力に出力します。 、標準出力のみに出力します。
プログラムがエラー情報を出力する必要がある場合 (必ずしも例外ではありません。これらはプログラミング言語の構造であり、はるかに高いレベルで課せられます)、通常は「標準エラー」に出力されます。通常は fprintf
で行います 、印刷時に使用するファイル ストリームを受け入れます。ファイル ストリームは、書き込み用に開かれた任意のファイル (標準出力、標準エラー、または fopen
で開かれたその他のファイル) です。 または fdopen
.
fread
を使用して、ファイルが入力を読み取る必要がある場合は、「標準入力」が使用されます。 または fgets
、または getchar
.
これらのファイルはどれも簡単にリダイレクトできます シェルから、次のように:
cat /etc/passwd > /tmp/out # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err # redirect cat's standard error to /tmp/error
cat < /etc/passwd # redirect cat's standard input to /etc/passwd
または、エンチラーダ全体:
cat < /etc/passwd > /tmp/out 2> /tmp/err
重要な警告が 2 つあります。まず、「標準入力」、「標準出力」、および「標準エラー」は単なる規則です。彼らはとても強い 慣例ですが、次のようなプログラムを実行できるのは非常に良いという合意にすぎません:grep echo /etc/services | awk '{print $2;}' | sort
各プログラムの標準出力を、パイプライン内の次のプログラムの標準入力にフックします。
次に、ファイル ストリームを操作するための標準 ISO C 関数を指定しました (FILE *
オブジェクト) -- カーネル レベルでは、すべてのファイル記述子 (int
) です。 ファイル テーブルへの参照) と read
のようなはるかに低レベルの操作 と write
これは、ISO C 関数のハッピー バッファリングを行いません。シンプルに保ち、より簡単な機能を使用することを考えましたが、それでも代替手段を知っておく必要があると思いました. :)
標準入力 - これはファイルハンドルです
標準出力 - プロセスは従来の出力をこのファイル ハンドルに書き込みます。
標準誤差 - プロセスは診断出力をこのファイル ハンドルに書き込みます。
それは私ができる限り馬鹿げたものです:-)
もちろん、それはほとんど慣習によるものです。必要に応じて、診断情報を標準出力に書き込むことを妨げるものは何もありません。 3 つのファイル ハンドルを完全に閉じて、独自のファイルを I/O 用に開くこともできます。
プロセスが開始されると、これらのハンドルが既に開いているはずであり、それらから読み取りおよび/または書き込みを行うことができます。
デフォルトでは、おそらく端末デバイスに接続されています (例:/dev/tty
) ただし、シェルを使用すると、プロセスが開始する前に、これらのハンドルと特定のファイルやデバイス (または他のプロセスへのパイプライン) との間の接続をセットアップできます (可能な操作のいくつかはかなり巧妙です)。
例:
my_prog <inputfile 2>errorfile | grep XYZ
my_prog
のプロセスを作成する .inputfile
を開く 標準入力 (ファイルハンドル 0) として。errorfile
を開く 標準エラーとして (ファイル ハンドル 2)。- 別の作成
grep
の処理 . my_prog
の標準出力を添付grep
の標準入力へ .
あなたのコメントについて:
<ブロック引用>/dev フォルダーでこれらのファイルを開くと、実行中のプロセスの出力が表示されないのはなぜですか?
通常のファイルではないためです。 UNIX はすべてを提供しますが、 どこかのファイルシステム内のファイルとして、それは最下位レベルではそうしません。 /dev
内のほとんどのファイル 階層は、文字デバイスまたはブロック デバイスのいずれかであり、実質的にはデバイス ドライバーです。サイズはありませんが、デバイスのメジャー番号とマイナー番号があります。
それらを開くと、物理ファイルではなくデバイス ドライバーに接続されます。デバイス ドライバーは、個別のプロセスを個別に処理する必要があることを認識できるほどスマートです。
同じことが Linux /proc
にも当てはまります。 ファイルシステム。これらは実際のファイルではなく、厳密に制御されたカーネル情報へのゲートウェイです。
上記の回答の補足として、リダイレクトについてまとめます。
編集:この図は完全に正しくありません.
最初の例では stdin をまったく使用せず、"hello" を引数として echo コマンドに渡しています。
グラフィックには、2>&1 は &> と同じ効果があるとも書かれていますが、
ls Documents ABC > dirlist 2>&1
#does not give the same output as
ls Documents ABC > dirlist &>
これは、&> にはリダイレクト先のファイルが必要であり、2>&1 は単純に stderr を stdout に送信するためです