Я только начал изучать, как все это файл TM в Linux, что заставило меня задуматься, что произойдет, если я в буквальном смысле прочитал из / dev / stdout:
$ cat /dev/stdout
^C
$ tail /dev/stdout
^C
(Это ^C
я убиваю программу после зависания).
Когда я пытаюсь сделать это vim
, я получаю немыслимое сообщение: «/ dev / stdout» - это не файл. Gasp!
Так, что дает, почему я получаю зависания или сообщения об ошибках, когда я пытаюсь прочитать эти "файлы"?
Ответы:
Вы не получаете "зависания" от,
cat(1)
иtail(1)
они просто блокируют чтение.cat(1)
ожидает ввода и печатает его, как только видит полную строку:Здесь я напечатал
foo
Enterbar
EnterCTRL- D.tail(1)
ожидает ввода и печатает его только тогда, когда он может обнаружитьEOF
:Здесь я снова наберется
foo
Enterbar
EnterCTRL- D.Vim - единственный, кто выдает ошибку. Это происходит потому, что он работает
stat(2)
против/dev/stdout
, и обнаруживает, чтоS_IFREG
бит не установлен./dev/stdout
это файл, но не обычный файл. На самом деле, в ядре есть некоторый танец, чтобы дать ему запись в файловой системе. В Linux:На OpenBSD:
На FreeBSD:
источник
(Почти) все это файл, но не все это обычный файл. Не имеет смысла вызывать текстовый редактор для чего-то особенного, такого как каталог, сетевой сокет, последовательный порт и т. Д.
Файл
/dev/stdout
может быть одним из нескольких в зависимости от варианта Unix:В любом случае при открытии
/dev/stdout
и аналогичных файлах создается новый файловый дескриптор, связанный с тем же файлом, который приложение уже открыло в файловом дескрипторе 1. «Стандартный вывод» означает файловый дескриптор 1, и этот дескриптор файла используется только в соответствии с соглашением для вывода - ядру все равно.Когда вы запускаете программу в терминале, на терминальном устройстве открываются все три стандартных дескриптора (0 = стандартный ввод, 1 = стандартный вывод, 2 = стандартная ошибка). Чтение с этого устройства возвращает символы, набранные пользователем, а запись на это устройство отображает текст в окне терминала. (Для терминального устройства нет стандартного способа прочитать вывод, который он отображает, или ввести ввод в него.)
Когда вы запускаете
cat /dev/stdout
, это делает то же самое, что иcat /dev/stdin
orcat /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
, он жалуется, потому что не знает, как редактировать терминал (это просто не имеет смысла).источник
cat
иtail
ищите дополнительный контент с последующим концом файла./dev/stdout
остается открытым, поэтомуcat
иtail
продолжай искать.источник