Я попытался выполнить следующую команду:

cat | less

Я знаю, что обе команды требуют чего-то от стандартного ввода. Когда я запустил его, это то, что я ожидал: все мои входные данные отправляются в cat, и я не смогу отправлять команды на меньше (в конце концов, не имея возможности выйти из программы с помощью команды q .).

Это не то, что происходит. На самом деле, он работает правильно, пока количество строк, отправляемых в стандартном вводе, меньше, чем количество строк на экране. Когда число строк, отправленных в стандартном вводе, стало больше, чем количество строк моего утешения, появляется странное поведение. Кажется, что входные данные отправляются иногда cat , иногда less . Например, неважно, буква q sometims позволяет программе выйти.

Почему причина такого поведения, которого я (наивно) не ожидал?

2 ответа2

2

CAT примет ввод от stdin (хотя, возможно, он более разумно предпочитает ввод из файла или канала), и выдает его на STDOUT

Это означает, что ввод просто передается через cat, а затем направляется на меньшее. Таким образом, вы можете увидеть результат меньше.

Ваши путаницы, скорее всего, приходят с буферизацией. CAT буферизует входные данные и будет пакетировать их (или ожидает окончания файла) при отправке на less для форматирования.

2

Я ненавижу себя за то, что говорю это, но

Есть больше чем один способ снять кожу с cat .

Под этим я подразумеваю стандартный ввод, а затем стандартный ввод.  Или чтение с клавиатуры (терминала), а затем чтение с клавиатуры.  Пытаться

less < afilename

Это работает так же, как

less afilename

Это означает, что less должно иметь какой-либо способ чтения с клавиатуры, кроме чтения со стандартного ввода.  Вот еще одна команда, которая работает, даже если вы этого не ожидаете:

less afilename < /dev/null

Посмотрите на команду tty.  Он сообщает имя tty (терминала), подключенного к стандартному входу.  Он работает, вызывая библиотечную функцию ttyname с аргументом 0 (файловый дескриптор стандартного ввода).

less вероятно , вызывая ttyname(1) , чтобы получить имя TTY (терминал) , подключенный к стандартному выходу.  Затем он открывает этот tty для чтения и принимает от него команды.  Он не читает команды из стандартного ввода; это только для данных.

Итак, у нас есть два квазинезависимых процесса (cat и less), независимо (одновременно) считывающих с клавиатуры (т. Е. Tty / терминал) по двум независимым файловым дескрипторам.  Это запутанная ситуация, и это что-то вроде «состояния гонки».  Я нахожу это чем-то аналогичным действию автомата для игры в пинбол, в котором есть множество дорожек или дорожек, по которым может пройти мяч - и он всегда занимает одну ; это никогда не может занять больше, чем один.  Точно так же, когда несколько процессов читают с одного и того же терминала одновременно, каждая набранная строка (если терминал находится в режиме строки) или каждый набранный символ (если терминал находится в режиме ввода символов) переходит ровно к одному процессу.  И выбор произвольный, мало чем отличающийся от действия пинбола.  Он не полностью «случайный», не более чем случайное планирование процессов; но это по сути непредсказуемо.

Итак, вот что происходит:

  • cat читает со своего стандартного входа, который по умолчанию является терминалом, и записывает в свой стандартный вывод, который является каналом для less .
  • В какой-то момент, less вызывает ttyname(1) , получает имя терминала, на котором он находится, и открывает его для чтения.
  • less читает полный экран данных (т.е. 24 строки или что-то еще) со своего стандартного ввода (канал) и записывает их в стандартный вывод (терминал).
  • Затем less выдает приглашение : переводит терминал в символьный режим и начинает чтение с терминала (не со стандартного ввода).
  • Итак, теперь у нас есть два процесса (cat и less), считывающих данные с терминала одновременно, и включается феномен пинбола - символы (и / или строки), которые вы вводите, переходят либо к cat либо к less полуслучайному.  Если он переходит к cat , он записывается в канал и less воспринимает его как данные.  Если он идет less оно интерпретируется как less команды.

Это не имеет ничего общего с буферизацией.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .