私はシステムコールを「読む」ためにstdout fdを渡しましたが、それでもうまくいきます。

私はシステムコールを「読む」ためにstdout fdを渡しましたが、それでもうまくいきます。

1(stdout)/ 2(stderr)をreadシステムコールに渡しましたが、まだうまくいきます。それから0(stdin)をwriteシステムコールに渡し、それがうまくいくことがわかりました!

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を使って書くことができますか?

三流です(標準入力、標準出力、標準エラー)内部一つ小川?

そうでなければ、なぜこのような結果が出るのでしょうか?

ベストアンサー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端末に表示されません。

おすすめ記事