web-dev-qa-db-ja.com

テキストエディタで/ dev / stdoutを読み取れないのはなぜですか?

私は方法を学び始めました すべてがファイルですTM Linuxでは、文字通り/ dev/stdoutから読み取るとどうなるのだろうと思いました。

$ cat /dev/stdout 
^C
$ tail /dev/stdout 
^C

^Cがハングした後、プログラムを強制終了しています。

vimを試してみると、「/ dev/stdout」はファイルではありません。ギャスプ!

では、これらの「ファイル」を読み込もうとすると、ハングアップやエラーメッセージが表示されるのはなぜですか。

9
user1717828

なぜハングアップするのですか

cat(1)およびtail(1)から「ハングアップ」を取得していません。読み取り時にブロックしているだけです。 cat(1)は入力を待機し、完全な行が見つかるとすぐに出力します。

_$ cat /dev/stdout
foo
foo
bar
bar
_

ここでfooと入力しましたEnterbarEnterCTRL-D

tail(1)は入力を待機し、EOFを検出できる場合にのみ出力します。

_$ tail /dev/stdout
foo
bar
foo
bar
_

ここでもう一度入力しましたfooEnterbarEnterCTRL-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
_
11
lcd047

(ほとんど)すべてがファイルですが、すべてが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を実行すると、ターミナルの編集方法がわからないため、文句を言われます(意味がありません)。

cattailは、オプションのコンテンツに続いてファイルの終わりを探しています。 /dev/stdoutは開いたままなので、cattailは見続けるだけです。

2
Politank-Z