Подтвердить что ты не робот

Меньше получает ввод клавиатуры от 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 - это способ сообщить об ошибках на экран и прочитать с клавиатуры? Я не думаю, что я в Канзасе больше...

4b9b3361

Ответ 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.