Меньше получает ввод клавиатуры от stderr?
Я просматриваю код утилиты "less", а именно, как он получает ввод на клавиатуре. Интересно, что в строке 80 ttyin.c он задает дескриптор файла для чтения из:
/*
* Try /dev/tty.
* If that doesn't work, use file descriptor 2,
* which in Unix is usually attached to the screen,
* but also usually lets you read from the keyboard.
*/
#if OS2
/* The __open() system call translates "/dev/tty" to "con". */
tty = __open("/dev/tty", OPEN_READ);
#else
tty = open("/dev/tty", OPEN_READ);
#endif
if (tty < 0)
tty = 2;
Не является файловым дескриптором 2 stderr? Если да, то WTH?! Я думал, что ввод с клавиатуры был отправлен через stdin.
Интересно, что даже если вы делаете ls -l * | less
, после того, как файл закончит загрузку, вы все равно можете использовать клавиатуру для прокрутки вверх и вниз, но если вы сделаете ls -l * | vi
, тогда vi будет кричать на вас, потому что это не читать с stdin. Какая большая идея? Как я попал на эту странную новую землю, где stderr - это способ сообщить об ошибках на экран и прочитать с клавиатуры? Я не думаю, что я в Канзасе больше...
Ответы
Ответ 1
$ ls -l /dev/fd/
lrwx------ 1 me me 64 2009-09-17 16:52 0 -> /dev/pts/4
lrwx------ 1 me me 64 2009-09-17 16:52 1 -> /dev/pts/4
lrwx------ 1 me me 64 2009-09-17 16:52 2 -> /dev/pts/4
При регистрации в промежуточном терминале все три стандартных дескриптора файла указывают на одно и то же: ваш TTY (или псевдоТТ).
$ ls -fl /dev/std{in,out,err}
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdin -> fd/0
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdout -> fd/1
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stderr -> fd/2
По соглашению мы читаем от 0
и записываем в 1
и 2
. Однако ничего не мешает нам делать иначе.
Когда ваша оболочка запускает ls -l * | less
, она создает канал из дескриптора файла ls
1
в less
дескриптор файла 0
. Очевидно, что less
больше не может читать ввод пользовательской клавиатуры из дескриптора файла 0
– он пытается вернуть TTY, но может.
Если less
не был отсоединен от терминала, open("/dev/tty")
предоставит ему TTY.
Однако, если это не удается... что вы можете сделать? less
делает последнюю попытку получения TTY, считая, что файловый дескриптор 2
прикреплен к тому же, к которому будет прикреплен дескриптор файла 0
, если он не был перенаправлен.
Этот не защищен:
$ ls -l * | setsid less 2>/dev/null
Здесь less
получает свой собственный сеанс (поэтому он больше не является частью активной группы процессов терминала, что приводит к сбою open("/dev/tty")
), и его файловый дескриптор 2
был изменен и ndash; теперь less
выходит немедленно, потому что он выводит на TTY, но он не может получить никакого ввода пользователя.
Ответ 2
Ну... сначала вы, кажется, пропустили вызов open()
, который открывает '/dev/tty'. Он использует только дескриптор файла 2, если вызов open() завершается с ошибкой. В стандартной системе Linux и, возможно, во многих Unices существует "/dev/tty" и вряд ли вызовет сбой.
Во-вторых, комментарий наверху дает ограниченное количество объяснений, почему они возвращаются к файловому дескриптору 2. Я предполагаю, что stdin
, stdout
и stderr
в значительной степени связаны с '/dev/tty/'в любом случае, если не перенаправлено. А поскольку наиболее распространенные перенаправления для stdin и/или stdout (через трубопровод или <
/>
), но реже для stderr
, коэффициенты заключаются в том, что использование stderr
скорее всего будет оставаться подключенным на "клавиатуру".
Ответ 3
Тот же вопрос с ответом в конечном счете от человека, который его спросил, находится на linuxquestions, хотя они цитируют немного другой источник из less
. И нет, я не понимаю большую часть этого, поэтому я не могу помочь дальше этого:)
Ответ 4
Похоже, что это специфическая для Linux функция, которая отправляет ввод с клавиатуры в FD 2.