Почему я не могу прочитать / dev / stdout в текстовом редакторе?

9

Я только начал изучать, как все это файл TM в Linux, что заставило меня задуматься, что произойдет, если я в буквальном смысле прочитал из / dev / stdout:

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

(Это ^Cя убиваю программу после зависания).

Когда я пытаюсь сделать это vim, я получаю немыслимое сообщение: «/ dev / stdout» - это не файл. Gasp!

Так, что дает, почему я получаю зависания или сообщения об ошибках, когда я пытаюсь прочитать эти "файлы"?

user1717828
источник
1
То, что vim рассматривает как файл, и что означает «все - это файл» (без ассоциированного товарного знака) в * nix, - это не одно и то же. Смотрите, например, № 1 и № 2 .
Златовласка

Ответы:

11

почему я получаю зависания

Вы не получаете "зависания" от, cat(1)и tail(1)они просто блокируют чтение. cat(1)ожидает ввода и печатает его, как только видит полную строку:

$ cat /dev/stdout
foo
foo
bar
bar

Здесь я напечатал fooEnterbarEnterCTRL- D.

tail(1)ожидает ввода и печатает его только тогда, когда он может обнаружить EOF:

$ tail /dev/stdout
foo
bar
foo
bar

Здесь я снова наберется fooEnterbarEnterCTRL- D.

или сообщения об ошибках

Vim - единственный, кто выдает ошибку. Это происходит потому, что он работает stat(2) против /dev/stdout, и обнаруживает, что S_IFREGбит не установлен.

/dev/stdoutэто файл, но не обычный файл. На самом деле, в ядре есть некоторый танец, чтобы дать ему запись в файловой системе. В 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
lcd047
источник
5

(Почти) все это файл, но не все это обычный файл. Не имеет смысла вызывать текстовый редактор для чего-то особенного, такого как каталог, сетевой сокет, последовательный порт и т. Д.

Файл /dev/stdoutможет быть одним из нескольких в зависимости от варианта Unix:

  • «специальный» файл, обычно символьное устройство;
  • «магическая» символическая ссылка, указывающая на файл, который процесс, обращающийся к нему, открыл в этом дескрипторе;
  • символическая ссылка на один из вышеперечисленных.

В любом случае при открытии /dev/stdoutи аналогичных файлах создается новый файловый дескриптор, связанный с тем же файлом, который приложение уже открыло в файловом дескрипторе 1. «Стандартный вывод» означает файловый дескриптор 1, и этот дескриптор файла используется только в соответствии с соглашением для вывода - ядру все равно.

Когда вы запускаете программу в терминале, на терминальном устройстве открываются все три стандартных дескриптора (0 = стандартный ввод, 1 = стандартный вывод, 2 = стандартная ошибка). Чтение с этого устройства возвращает символы, набранные пользователем, а запись на это устройство отображает текст в окне терминала. (Для терминального устройства нет стандартного способа прочитать вывод, который он отображает, или ввести ввод в него.)

Когда вы запускаете cat /dev/stdout, это делает то же самое, что и cat /dev/stdinor cat /dev/stderr, потому что эти три файловых дескриптора подключены к одному и тому же файлу: он сообщает 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, он жалуется, потому что не знает, как редактировать терминал (это просто не имеет смысла).

Жиль "ТАК - прекрати быть злым"
источник
2

catи tailищите дополнительный контент с последующим концом файла. /dev/stdoutостается открытым, поэтому catи tailпродолжай искать.

Politank-Z,
источник