私は方法を学び始めました すべてがファイルですTM Linuxでは、文字通り/ dev/stdoutから読み取るとどうなるのだろうと思いました。
$ cat /dev/stdout
^C
$ tail /dev/stdout
^C
(^C
がハングした後、プログラムを強制終了しています。
vim
を試してみると、「/ dev/stdout」はファイルではありません。ギャスプ!
では、これらの「ファイル」を読み込もうとすると、ハングアップやエラーメッセージが表示されるのはなぜですか。
なぜハングアップするのですか
cat(1)
およびtail(1)
から「ハングアップ」を取得していません。読み取り時にブロックしているだけです。 cat(1)
は入力を待機し、完全な行が見つかるとすぐに出力します。
_$ cat /dev/stdout
foo
foo
bar
bar
_
ここでfoo
と入力しましたEnterbar
EnterCTRL-D。
tail(1)
は入力を待機し、EOF
を検出できる場合にのみ出力します。
_$ tail /dev/stdout
foo
bar
foo
bar
_
ここでもう一度入力しましたfoo
Enterbar
EnterCTRL-D。
またはエラーメッセージ
Vimだけがエラーを表示します。 runsstat(2)
を_/dev/stdout
_に対して実行し、_S_IFREG
_ビットが設定されていないことが判明したためです。
_/dev/stdout
_はファイルですが、regularファイルではありません。実際、カーネルにはファイルシステムのエントリを与えるためのダンスがいくつかあります。 Linuxの場合:
_$ ls -l /dev/stdout
lrwxrwxrwx 1 root root 15 May 8 19:42 /dev/stdout -> /proc/self/fd/1
_
OpenBSDの場合:
_$ ls -l /dev/stdout
crw-rw-rw- 1 root wheel 22, 1 May 7 09:05:03 2015 /dev/stdout
_
FreeBSDの場合:
_$ ls -l /dev/stdout
lrwxr-xr-x 1 root wheel 4 May 8 21:35 /dev/stdout -> fd/1
$ ls -l /dev/fd/1
crw-rw-rw- 1 root wheel 0x18 May 8 21:35 /dev/fd/1
_
(ほとんど)すべてがファイルですが、すべてがregularファイルではありません。ディレクトリ、ネットワークソケット、シリアルポートなどの特別なファイルでテキストエディターを呼び出すのは意味がありません。
ファイル/dev/stdout
は、UNIXのバリアントに応じて、次のいずれかになります。
いずれの場合でも、/dev/stdout
および類似のファイルを開くと、アプリケーションがファイル記述子1ですでに開いている同じファイルに関連付けられた新しいファイル記述子が作成されます。「標準出力」はファイル記述子1を意味し、このファイル記述子は出力に使用されます—カーネルは関係ありません。
端末でプログラムを実行すると、3つの標準記述子(0 =標準入力、1 =標準出力、2 =標準エラー)がすべて端末デバイスで開かれます。そのデバイスから読み取ると、ユーザーが入力した文字が返され、そのデバイスに書き込むと、ターミナルウィンドウにテキストが表示されます。 (端末デバイスが与えられた場合、表示する出力を読み取る、またはそこに入力を注入する標準的な方法はありません。)
cat /dev/stdout
を実行すると、cat /dev/stdin
またはcat /dev/stderr
とまったく同じことになります。これらの3つのファイル記述子は同じファイルに接続されているため、cat
に読み取りを指示します。ターミナルから。これは、引数なしのcat
も同じです。
cat /dev/stdout >foo
を実行した場合、/dev/stdout
はファイルfoo
を参照します—このコマンドはcat foo >foo
と同等です。 cat
の実装に応じて、エラーが発生するか(GNUバージョンは「入力ファイルは出力ファイル」であると報告します)、または空のファイルfoo
(>foo
は切り捨てただけです)cat
が空でない場合、この特殊なケースを検出しないfoo
のバージョンでは次に、cat /dev/stdout >>foo
または同等のcat foo >>foo
は、ファイルのコンテンツをそれ自体に無期限に追加します。
vim /dev/stdout
を実行すると、ターミナルの編集方法がわからないため、文句を言われます(意味がありません)。
cat
とtail
は、オプションのコンテンツに続いてファイルの終わりを探しています。 /dev/stdout
は開いたままなので、cat
とtail
は見続けるだけです。