Вопрос

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

Это было полезно?

Решение

$ 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 файлового дескриптора less в open("/dev/tty") файловый дескриптор <=>. Очевидно, <=> больше не может читать ввод с клавиатуры пользователя из файлового дескриптора <=> & # 8211; он пытается вернуть TTY как может.

Если <=> не был отсоединен от терминала, <=> предоставит ему TTY.

Однако, в случае неудачи ... что вы можете сделать? <=> делает последнюю попытку получения TTY, предполагая, что дескриптор файла <=> присоединен к тому же объекту, к которому был бы прикреплен дескриптор файла <=>, если бы он не был перенаправлен.

Это не является отказоустойчивым:

$ ls -l * | setsid less 2>/dev/null

Здесь <=> присваивается собственный сеанс (поэтому он больше не является частью активной группы процессов терминала, что приводит к сбою <=>), а его дескриптор файла <=> был изменен & # 8211; теперь <=> немедленно завершается, поскольку он выводится на TTY, но не может получить какой-либо пользовательский ввод.

Другие советы

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top