stdout fd を 'read' システムコールに渡しますが、それでも正常に動作します

stdout fd を 'read' システムコールに渡しますが、それでも正常に動作します

1システム コールに(stdout)/ 2(stderr)を渡しましたが、それでも正常に動作します。次に、システム コールに (stdin)readを渡すと、これも動作することがわかりました。0write

int main(int argc, char** argv){
    char buf[1024] = "abcdefghi\n";

    write(0, buf, 10);

    char readbuf[1024] = {0};
    // read(1, readbuf, 10); works too
    read(2, readbuf, 10);
    write(2, readbuf, 10);

    return 0;
}

出力:

abcdefghi
hey stdin  <-- I input this
hey stdin

混乱して、エラーだと思いました。

実験:

次に、fd 2 をリダイレクトしてみました。

$ ./a.out 2>/dev/null

今回は読み取りと2回目の書き込みはどちらも「表示」されません。出力は次のようになります。

abcdefgi

それで、stderr は読み取りに使用できますか?

次に、stdout と stderr を閉じて、stdin のコピーを 2 つ作成します。

int main(int argc, char** argv){
    char buf[1024] = "abcdefghi\n";

    close(1);
    close(2);

    dup2(0, 1);
    dup2(0, 2);

    write(0, buf, 10);

    char redbuf[1024] = {0};
    read(2, redbuf, 10);
    write(2, redbuf, 10);

    return 0;
}

再び動作します。

出力:

abcdefghi
hey stdin  <-- I input this
hey stdin

では、stdin は書き込みに使用できるのでしょうか?

ここで説明が必要です。

質問

私は知りたいです:

なぜ stdout/stderr を読み取りに使用できるのですか?

なぜ stdin を書き込みに使用できるのですか?

3つの流れは(標準入力、標準出力、標準エラー出力) 内部的に1つストリーム ?

そうでない場合、なぜこの結果になるのでしょうか?

答え1

入力/出力/エラーに fd 0/1/2 を使用するのは慣例です。リダイレクトなしでプログラムを呼び出すと、3 つすべてが tty を参照し、tty は読み取りおよび書き込みアクセスで開かれます。つまり、必要に応じて読み取りまたは書き込みを行うことができます。これらを同じストリームと呼ぶこともできますが、ストリームという表現は、FILEC やstreamC++ などの高レベル I/O によく使用されます。

これが、リダイレクトされた例とリダイレクトされていない例の両方が、入力したテキストをそのままエコーする理由です。

一方、リダイレクトを行う場合、シェルは読み取り専用または書き込み専用アクセスでファイルを開きます。 の例では./a.out 2>/dev/null、 への書き込みは0リダイレクトされていないため、端末に接続されたままであり、そのため画面に表示されます。 からの読み取りは2書き込み専用に接続されている/dev/nullため失敗するはずですが、プログラムからその違いに気付くことはありません。 への書き込みは2成功しますが、 に書き込まれます/dev/null。 への無効な読み取りと への有効な書き込みは、/dev/null端末には表示されません。

答え2

stdin/stdout/stderr をリダイレクトしない限り、これらのファイル記述子はログイン プロシージャによって開かれ、関連するものがtty最初のファイルとして読み取りと書き込み用に開かれ (ファイル記述子 #0 になります)、その後 2 回呼び出されてdup()stdout と stderr のファイル記述子が取得されます。

前述の通り`less` はどのようにしてユーザーからのコマンドを読み取りながら stdin からデータを取得するのでしょうか?以前(/dev/ttyが導入される前UNIX)は、 のようなプログラムは確認を求めるときmoreに から読み取りを行っていました。stderr

関連情報