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

Интересно, даже если вы делаете ls -l * | lessПосле завершения загрузки файла вы все равно можете использовать клавиатуру для прокрутки вверх и вниз, но если вы это сделаете ls -l * | vi, тогда vi будет кричать на тебя, потому что он не читает с stdin. Что за большая идея? Как я оказался в этой странной новой стране, где stderr - это способ сообщать об ошибках на экран и читать с клавиатуры? Я не думаю, что я в Канзасе больше...

4 ответа

Решение
$ 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 (или псевдо-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 был изменен - ​​сейчас less выходит немедленно, потому что он выводит на TTY, но не получает никакого пользовательского ввода.

Ну... во-первых, вы, кажется, пропустили open() вызов, который открывает '/dev/tty'. Он использует файловый дескриптор 2 только в случае сбоя вызова open(). В стандартной системе Linux и, вероятно, во многих Unix-файлах существует / dev / tty, и он вряд ли вызовет сбой.

Во-вторых, комментарий вверху дает ограниченное количество объяснений, почему они возвращаются к файловому дескриптору 2. Я предполагаю, что stdin, stdout, а также stderr в любом случае, в значительной степени связаны с /dev/tty/, если не перенаправлены. И так как наиболее распространенные перенаправления для для стандартного ввода и / или стандартного вывода (через трубопровод или < / >), но реже для stderrшансы на то, что с помощью stderr Скорее всего, все еще будет подключен к "клавиатуре".

Тот же вопрос с ответом, в конечном счете, от человека, который его задал, находится на linuxquestions, хотя они цитируют немного другой источник из less, И нет, я не понимаю большинство из них, поэтому я не могу помочь в этом:)

Похоже, это специфическая функциональность Linux, которая отправляет ввод с клавиатуры на FD 2.

Другие вопросы по тегам