ファイル記述子レベルでは、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