2

Я вошел в терминал (или эмулятор терминала), читаю man-страницы или читаю файл с less и т.д. Я использую Ctrl - Z, чтобы приостановить приложение переднего плана, вернуться в оболочку (bash), сделать что-то, вернуться в полноэкранное приложение, снова выйти и т.д.

В конце концов, но обычно не во время первой итерации, Ctrl - Z не приведет меня к командной строке, но останется в промежуточном состоянии, когда ввод с клавиатуры отображается на терминале, редактирование readline недоступно, удаление backspace работает и ввод ввода дается оболочке при нажатии Enter.

Может кто-нибудь объяснить, почему это происходит и как это отключить? Я не нашел никаких ссылок на это явление в Интернете, хотя я сталкивался с ним в течение многих лет.

1 ответ1

1

Я могу объяснить это, но я не знаю, как это исправить. Это беспокоило меня годами тоже. Не менее 20 Это не единственная ошибка в какой-либо конкретной программе, а условие состязания между 3 программами, которые по отдельности ведут себя как задумано, и достаточно общее, что оно применимо ко многим комбинациям программ.

Когда вы читаете ^Z во время чтения страницы руководства, вы отправляете SIGTSTP в группу процессов переднего плана, которая состоит из процесса man и его потомков. Пейджер (less) является одним из тех потомков.

man немедленно отстранен, но less нет. У него есть обработчик сигнала. И для этого есть веская причина. Он изменил режим tty (так что он может читать символы, как только они набраны), и он хочет восстановить исходный режим и привести в порядок экран перед тем, как отказаться от контроля. Так оно и есть.

Между тем (это редкое слово) оболочка заметила, что процесс man остановлен. И вот плохая часть: оболочка понятия не имеет, что существует less процесс. Unix-процессы, как правило, не имеют возможности узнать о своих внуках. Таким образом, с точки зрения оболочки, работа прекратилась, хотя на самом деле less еще не закончил уборку.

Обрабатывая неполную информацию, оболочка возвращается на передний план, печатает уведомление о задании, устанавливает режим tty для собственного редактора строк и печатает подсказку. Но это гонки с less , которые все еще пытаются привести в порядок. Пока оболочка печатает подсказку и настраивает режим atty, меньше занята перемещением курсора и очисткой нижней строки экрана (где было less подсказки).

Поскольку это гонка, есть много возможных результатов, в зависимости от порядка операций, но наиболее раздражающим является следующее:

  1. оболочка печатает уведомление о задании, устанавливает режим tty для своего редактора строк и печатает приглашение.
  2. less перемещает курсор в нижний левый угол, очищает нижнюю строку (стирая подсказку less и оболочку) и восстанавливает общий режим tty по умолчанию (режим "cooked").
  3. оболочка ставит себя на передний план и начинает принимать ввод.

Теперь вы смотрите на пустую строку, которой предшествует уведомление о задании, когда оболочка пытается прочитать нажатия клавиш, не зная, что tty был переведен в готовый режим, и поэтому не будет отправлять какие-либо входные данные в оболочку до полная строка набрана.

Вы можете набрать здесь команду и даже отредактировать ее, если вы достаточно умны, чтобы понять, как заставить ее работать, когда ваш ввод проходит через редактор строк tty и редактор строк оболочки, причем немедленная обратная связь поступает только от редактор линии tty.

Это сложная ситуация, и для ее исправления требуется больше координации между процессами, чем позволяет ядро. Для оболочки требуется способ запроса состояния приостановки группы процессов в целом и способ различения между процессами внуков, например, less которые обрабатывают SIGTSTP с намерением приостановить себя вскоре после этого, и демоноподобными внуками, которые просто игнорируют SIGTSTP с намерение продолжать работать в фоновом режиме, пока остальная часть работы приостановлена.

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