Как работают ввод с клавиатуры и вывод текста?

85

Предположим, я нажимаю Aклавишу в текстовом редакторе, и это вставляет символ aв документ и отображает его на экране. Я знаю, что приложение редактора напрямую не взаимодействует с оборудованием (между ядром и другими компонентами), так что происходит внутри моего компьютера?

жилль
источник

Ответы:

100

Есть несколько разных сценариев; Я опишу самые распространенные. Последовательные макроскопические события:

  1. Ввод: событие нажатия клавиши передается с клавиатуры на приложение.
  2. Обработка: приложение решает, что, поскольку клавиша Aбыла нажата, оно должно отображать символ a.
  3. Вывод: приложение выдает порядок отображения aна экране.

GUI приложения

Стандартным графическим пользовательским интерфейсом де-факто систем Unix является система X Window , часто называемая X11, потому что она стабилизировалась в 11-й версии своего основного протокола между приложениями и сервером отображения. Программа, называемая X-сервером, находится между ядром операционной системы и приложениями; он предоставляет услуги, включая отображение окон на экране и передачу нажатий клавиш в окно, которое имеет фокус.

вход

+----------+              +-------------+         +-----+
| keyboard |------------->| motherboard |-------->| CPU |
+----------+              +-------------+         +-----+
             USB, PS/2, …                 PCI, …
             key down/up

Сначала информация о нажатии и отпускании клавиши передается с клавиатуры на компьютер и внутри компьютера. Детали зависят от типа оборудования. Я не буду подробно останавливаться на этой части, потому что информация остается неизменной по всей этой части цепочки: определенная клавиша была нажата или отпущена.

         +--------+        +----------+          +-------------+
-------->| kernel |------->| X server |--------->| application |
         +--------+        +----------+          +-------------+
interrupt          scancode             keysym
                   =keycode            +modifiers

Когда происходит аппаратное событие, процессор запускает прерывание , которое вызывает выполнение некоторого кода в ядре . Этот код обнаруживает, что аппаратное событие представляет собой нажатие клавиши или отпускание клавиши с клавиатуры, и записывает код сканирования, который идентифицирует клавишу.

X-сервер читает входные события через файл устройства , например, /dev/input/eventNNNв Linux (где NNN - число). Всякий раз, когда происходит событие, ядро ​​сообщает, что есть данные для чтения с этого устройства. Файл устройства передает ключевые события вверх / вниз с помощью кода сканирования, который может совпадать или не совпадать со значением, передаваемым аппаратным обеспечением (ядро может преобразовывать код сканирования из зависимого от клавиатуры значения в общее значение, а Linux не не передавать коды сканирования, которые он не знает ).

X вызывает код сканирования, который читает код ключа . X-сервер поддерживает таблицу, которая переводит коды клавиш в ключевые символы (сокращение от «символ ключа»). Кодовые ключи являются числами, тогда как символы клавиш названия , такие как A, aacute, F1, KP_Add, Control_L, ... The может отличаться символ клавиши в зависимости от того, какие клавиши - модификаторы нажимаются ( Shift, Ctrl, ...).

Существует два механизма для настройки сопоставления кодов клавиш с ключами:

  • xmodmap - это традиционный механизм. Это простая таблица сопоставления кодов клавиш со списком ключевых символов (неизмененных, сдвинутых,…).
  • XKB - более мощный, но более сложный механизм с лучшей поддержкой большего количества модификаторов, в частности, для конфигурации с двумя языками, среди прочего.

Приложения подключаются к X-серверу и получают уведомление при нажатии клавиши, когда окно этого приложения находится в фокусе. В уведомлении указывается, что определенная клавиатура была нажата или отпущена, а также какие модификаторы были нажаты в данный момент. Вы можете увидеть ключевые слова, запустив программу xevиз терминала. Что приложение делает с информацией, зависит от нее; некоторые приложения имеют настраиваемую привязку клавиш.

В типичной конфигурации, когда вы нажимаете клавишу с надписью Aбез модификаторов, это отправляет keysym aв приложение; если приложение находится в режиме ввода текста, вставляется символ a.

Взаимосвязь раскладки клавиатуры и xmodmap более подробно рассматривается при вводе с клавиатуры. Как работают события мыши в Linux? дает обзор ввода мыши на более низких уровнях.

Выход

+-------------+        +----------+          +-----+         +---------+
| application |------->| X server |---····-->| GPU |-------->| monitor |
+-------------+        +----------+          +-----+         +---------+
               text or              varies          VGA, DVI,
               image                                HDMI, …

Есть два способа отображения персонажа.

См. Каковы цели различных типов шрифтов XWindows? для обсуждения клиентской и серверной визуализации текста под X11.

То, что происходит между X-сервером и графическим процессором (процессором на видеокарте), сильно зависит от оборудования. В простых системах X-сервер обращается в область памяти, называемую кадровым буфером , который графический процессор собирает для отображения. Усовершенствованные системы, такие как на любом ПК или смартфоне 21-го века, позволяют графическим процессорам выполнять некоторые операции напрямую для повышения производительности. В конечном счете, графический процессор передает изображение экрана пиксель за пикселем каждую долю секунды на монитор.

Приложение в текстовом режиме, работающее в терминале

Если ваш текстовый редактор является приложением текстового режима, работающим в терминале, то это терминал, который является приложением для целей приведенного выше раздела. В этом разделе я объясню интерфейс между приложением текстового режима и терминалом. Сначала я опишу случай эмулятора терминала, работающего под X11. Какова точная разница между терминалом, оболочкой, tty и консолью? Может быть полезным фоном здесь. Прочитав это, вы можете прочитать гораздо более подробно Каковы обязанности каждого компонента псевдотерминала (PTY) (программное обеспечение, ведущая сторона, ведомая сторона)?

вход

      +-------------------+               +-------------+
----->| terminal emulator |-------------->| application |
      +-------------------+               +-------------+
keysym                     character or
                           escape sequence

Эмулятор терминала получает события типа « Leftбыл нажат, когда Shiftбыл выключен». Интерфейсом между эмулятором терминала и приложением в текстовом режиме является псевдотерминал (pty) , символьное устройство, которое передает байты. Когда эмулятор терминала получает событие нажатия клавиши, он преобразует его в один или несколько байтов, которые приложение получает для чтения с pty-устройства.

Печатные символы вне диапазона ASCII передаются в виде одного или нескольких байтов в зависимости от символа и кодировки . Например, в UTF-8 кодировке Unicode , набор символов, символы в ASCII диапазоне кодируются как одного байта, в то время как символы за пределами этого диапазона кодируются в виде нескольких байт.

Нажатия клавиш, которые соответствуют функциональной клавише или печатному символу с модификаторами, такими как Ctrlили Alt, отправляются как escape-последовательность . Экранирующие последовательности обычно состоят из экранирующего символа (байтовое значение 27 = 0x1B = \033, иногда представляемое как ^[или \e), за которым следует один или несколько печатных символов. Некоторым клавишам или комбинациям клавиш соответствует управляющий символ, соответствующий им в кодировках на основе ASCII (которые в основном используются сегодня, включая Unicode): Ctrl+ letterвозвращает значение символа в диапазоне 1–26, Escявляется escape-символом видно выше и тоже самое что Ctrl+ [, Tabто же самое что и Ctrl+ I,Returnтакой же, как Ctrl+ Mи т. д.

Разные терминалы отправляют различные escape-последовательности для данной клавиши или комбинации клавиш. К счастью, обратное неверно: на практике для последовательности существует не более одной комбинации клавиш, которую она кодирует. Единственным исключением является символ 127 = 0x7f =, \0177который часто, Backspaceно иногда Delete.

В терминале, если вы набираете Ctrl+, Vа затем комбинацию клавиш, это вставляет первый байт escape-последовательности из комбинации клавиш буквально. Поскольку escape-последовательности обычно состоят только из печатных символов после первого, это буквально вставляет всю escape-последовательность. Видите таблицу привязок клавиш? для обсуждения Zsh в этом контексте.

Терминал может передавать одну и ту же escape-последовательность для некоторых комбинаций модификаторов (например, многие терминалы передают символ пробела для обоих символов Spaceи Shift+ Space; xterm имеет режим для различения комбинаций модификаторов, но терминалы, основанные на популярной библиотеке vte, этого не делают ). Несколько ключей вообще не передаются, например, клавиши-модификаторы или клавиши, которые запускают привязку эмулятора терминала (например, команда копирования или вставки).

Приложение может преобразовать escape-последовательности в имена символических ключей, если того пожелает.

Выход

+-------------+               +-------------------+
| application |-------------->| terminal emulator |--->
+-------------+               +-------------------+
               character or
               escape sequence

Вывод намного проще, чем ввод. Если приложение выводит символ в файл устройства pty, эмулятор терминала отображает его в текущей позиции курсора. (Эмулятор терминала поддерживает положение курсора и прокручивает, если курсор окажется под нижней частью экрана.) Приложение также может выводить escape-последовательности (в основном начинающиеся с ^[или ^]), чтобы сообщить терминалу выполнить такие действия, как перемещение курсора, изменение атрибутов текста (цвет, полужирный,…) или удаление части экрана.

Escape-последовательности, поддерживаемые эмулятором терминала, описаны в базе данных termcap или terminfo . Большинство терминальных эмуляторов в настоящее время довольно тесно связаны с xterm . Смотрите документацию по переменным LESS_TERMCAP_ *? для более подробного обсуждения информационных баз данных о возможностях терминала, а также как остановить мигание курсора и могу ли я установить цвета терминала моей локальной машины, чтобы использовать цвета машины, в которую я ввел ssh? для некоторых примеров использования.

Приложение работает в текстовой консоли

Если приложение работает непосредственно в текстовой консоли, то есть в терминале, предоставляемом ядром, а не в приложении эмулятора терминала, применяются те же принципы. Интерфейс между терминалом и приложением по-прежнему представляет собой поток байтов, который передает символы со специальными ключами и командами, закодированными как escape-последовательности.

Удаленное приложение, доступ к которому осуществляется через сеть

Удаленное текстовое приложение

Если вы запускаете программу на удаленном компьютере, например, через SSH , то сетевой протокол обмена данными передает данные на уровне pty.

+-------------+           +------+           +-----+           +----------+
| application |<--------->| sshd |<--------->| ssh |<--------->| terminal |
+-------------+           +------+           +-----+           +----------+
               byte stream        byte stream       byte stream
               (char/seq)         over TCP/…        (char/seq)

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

Удаленное приложение X11

Протокол связи между приложениями и сервером сам по себе является потоком байтов, который может быть отправлен по сетевому протоколу, такому как SSH.

+-------------+            +------+        +-----+            +----------+
| application |<---------->| sshd |<------>| ssh |<---------->| X server |
+-------------+            +------+        +-----+            +----------+
               X11 protocol        X11 over       X11 protocol
                                   TCP/…

Это в основном прозрачно, за исключением того, что некоторые функции ускорения, такие как декодирование фильмов и 3D-рендеринг, которые требуют прямой связи между приложением и дисплеем, недоступны.

жилль
источник
Не совсем уверен, но так как ответ, как правило, довольно подробный, мне интересно, если часть, которая говорит «Приложение работает в текстовой консоли», может не показывать, что такие вещи man 5 keymapsиспользуются для перевода keycodesв scancodes. Хотя, как уже упоминалось, в принципе схожий, он представляет собой совершенно другой набор инструментов / программ, и это заслуживает, возможно, еще большего понимания. Рядом с этим ответ +1 и отличный из-за встроенных связанных вопросов.
человечествоANDpeace
Я нашел PgUpи Ctrl+PgUpнеотличим в tty1 (TERM = linux). Можно ли настроить keysym -> отображение последовательности управления?
тушеное мясо
@stewbasic Да, с загруженной картой ключей loadkeys. Ищите вопросы с тегами linux на консоли, раскладка клавиатуры .
Жиль
@ Жиль, спасибо! Стоит отметить, что loadkeys изменяет оба отображения: keycode -> keysym и keysym -> escape-последовательность (для меня это изначально не было очевидно).
тушеное мясо
1
Вау, это должен быть один из лучших ответов, которые я когда-либо видел на Stackexchange - хорошо организованный, отвечает на вопрос, предоставляет соответствующий контекст, дает перекрестные ссылки на другие полезные ответы и даже имеет хорошее искусство ASCII!
Johntron
4

Если вы хотите увидеть это в Unix-системе, которая достаточно мала, чтобы быть понятной, погрузитесь в Xv6 . Это более или менее мифический Unix 6th Edition, который стал основой знаменитого комментария Джона Лайона , издававшегося как самиздат. Его код был переработан для компиляции под ANSI C и с учетом современных разработок, таких как мультипроцессоры.

vonbrand
источник