ファイル記述子レベルでは、stdin ファイル記述子 0 と定義されています 、stdout はファイル記述子 1 として定義されています;および stderr ファイル記述子 2 として定義されています .これを見てください。
プログラムまたはシェルが変更された場合でも (例:dup2(2) でリダイレクト)、ファイル記述子 0 は常に stdin のままです (定義により STDIN_FILENO
は 0 です)。
open(2) または pipe(2) または socket(2) のようなシステムコールは、例えばSTDIN_FILENO
(つまり、0) そのファイル記述子が空いている場合 (たとえば、以前に close(2)-d されたため)。ただし、それが発生した場合でも、stdin のままです
もちろん、stdio(3) では、FILE
ストリーム stdin はもう少し複雑です。プログラムは fclose(3)、freopen(3)、fdopen(3) ...
いくつかの回答が既に存在していましたが、完全なストーリーを説明するのに十分な情報が得られませんでした.
さらに調査を進めたので、調査結果を追加します。
プロセスが開始されるたびに、実行中のプロセスのエントリが /proc/<pid>
に追加されます ディレクトリ。これは、プロセスに関連するすべてのデータが保持される場所です。また、プロセスの開始時に、カーネルは 3 つのファイル記述子をプロセスに割り当て、stdin
と呼ばれる 3 つのデータ ストリームと通信します。 、 stdout
と stderr
.
Linux カーネルはアルゴリズムを使用して常に最小の整数値で FD を作成するため、これらのデータ ストリームは数値 0
にマップされます。 、 1
そして 2
.
これらはストリームへの参照にすぎないため、ストリームを閉じることができます。 close(<fd>)
を簡単に呼び出すことができます 、私たちの場合は close(1)
、ファイル記述子を閉じます。
ls -l /proc/<pid>/fd/
の実行について 、リストされている FD は 2 つだけです 0
と 2
.
ここで open()
を実行すると カーネルを呼び出すと、この新しいファイル参照をマップする新しい FD が作成されます。カーネルは最小の整数を最初に使用するため、整数値 1
を取得します。 .
これで、作成された新しい FD は、開いたファイルを指します (open()
を使用) システムコール)
現在行われているデータ転送は、以前にリンクされたデフォルトのデータ ストリームではなく、開いた新しいファイルを介して行われます。
はい、FD 0
をマッピングできます 、 1
または 2
stdin
不要 、 stdout
または stderr