
1
システム コールに(stdout)/ 2
(stderr)を渡しましたが、それでも正常に動作します。次に、システム コールに (stdin)read
を渡すと、これも動作することがわかりました。0
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 を書き込みに使用できるのですか?
3つの流れは(標準入力、標準出力、標準エラー出力) 内部的に1つストリーム ?
そうでない場合、なぜこの結果になるのでしょうか?
答え1
入力/出力/エラーに fd 0/1/2 を使用するのは慣例です。リダイレクトなしでプログラムを呼び出すと、3 つすべてが tty を参照し、tty は読み取りおよび書き込みアクセスで開かれます。つまり、必要に応じて読み取りまたは書き込みを行うことができます。これらを同じストリームと呼ぶこともできますが、ストリームという表現は、FILE
C やstream
C++ などの高レベル 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