Терминальные эмуляторы
Главная сторона заменяет линию (пару проводов TX / RX), которая идет к терминалу.
Терминал отображает символы, которые он получает на одном из проводов (некоторые из них являются управляющими символами и заставляют его выполнять такие действия, как перемещение курсора, изменение цвета ...), и отправляет на другом проводе символы, соответствующие клавишам, которые вы вводите.
Эмуляторы терминала, такие как xterm, ничем не отличаются, за исключением того, что вместо отправки и получения символов по проводам они читают и записывают символы в своем файловом дескрипторе на главную сторону. Как только они породили подчиненный терминал и запустили вашу оболочку, они больше не трогали это. В дополнение к эмуляции пары проводов, xterm может также изменить некоторые свойства дисциплины линии через этот файловый дескриптор на сторону мастера. Например, они могут обновить атрибуты размера, чтобы SIGWINCH отправлялся приложениям, которые взаимодействуют с ведомым pty, чтобы уведомить их об измененном размере.
Кроме этого, в эмуляторе терминала / терминала мало интеллекта .
То, что вы пишете на терминальное устройство (например, pty-slave), это то, что вы имеете в виду, чтобы отображаться там, то, что вы читаете с него, это то, что вы там набрали, так что эмулятору терминала не имеет смысла читать или писать на него. , Они на другом конце.
Дисциплина линии tty
Много интеллекта находится в с TTY дисциплины линии . Линейная дисциплина - это программный модуль (находящийся в драйвере, в ядре), помещенный поверх последовательного / pty-устройства, которое находится между этим устройством и линией / проводом (ведущей стороной для pty).
Последовательная линия может иметь терминал на другом конце, а также мышь или другой компьютер для работы в сети. Вы можете прикрепить дисциплину линии SLIP, например, чтобы получить сетевой интерфейс поверх последовательного устройства (или устройства pty), или у вас может быть дисциплина линии tty . Дисциплина линии tty является дисциплиной линии по умолчанию, по крайней мере, в Linux для последовательных и pty-устройств. В Linux вы можете изменить дисциплину строки с помощью ldattach
.
Вы можете увидеть эффект отключения дисциплины tty line с помощью команды stty raw -echo
(обратите внимание, что приглашение bash или другие интерактивные приложения, например, vi
устанавливают терминал в нужном им режиме, поэтому вы хотите использовать тупое приложение, подобное cat
этому). Затем все, что записано на ведомое оконечное устройство, сразу же отправляется на ведущую сторону для чтения xterm, и каждый символ, записанный xterm на ведущую сторону, сразу же доступен для чтения с ведомого устройства.
В дисциплине линии реализован редактор внутренней линии терминала . Например, с помощью stty icanon echo
(как по умолчанию), когда вы a
печатаете, xterm записывает a
в мастер, то дисциплина строки повторяет его обратно (делает a
доступным для чтения xterm
для отображения), но не делает ничего доступным для чтения на ведомой стороне. , Затем, если вы набираете backspace, xterm отправляет символ ^?
или ^H
, дисциплина строки (как таковая ^?
или ^H
соответствует erase
настройке дисциплины строки) отправляет обратно на мастер a ^H
, space
и ^H
для xterm
удаленияa
вы только что набрали на его экране и все еще ничего не отправляете в приложение, читающее со стороны ведомого устройства, оно просто обновляет свой внутренний буфер редактора строк, чтобы удалить то, что a
вы ввели ранее.
Затем, когда вы нажимаете Enter, xterm передает ^M
(CR), который дисциплина строки преобразует при вводе в ^ J (LF), и отправляет то, что вы ввели до сих пор, для чтения на ведомой стороне (приложение /dev/pts/x
, получающее чтение , получит то, что вы ввели, включая LF, но не тот, который a
вы удалили), в то время как на главной стороне он посылает CR и LF, чтобы переместить курсор на следующую строку и начало экрана.
Дисциплина линии также отвечает за отправку SIGINT
сигнала группе процессов терминала переднего плана, когда он получает ^C
символ на стороне мастера и т. Д.
Многие интерактивные терминальные приложения отключают большинство функций этой линейной дисциплины, чтобы реализовать их самостоятельно. Но в любом случае, имейте в виду, что терминал ( xterm
) не имеет к этому никакого отношения (кроме отображения того, что сказано для отображения).
И может быть только один сеанс на процесс и на оконечное устройство. К сеансу может быть подключен управляющий терминал, но это не обязательно (все сеансы начинаются без терминала, пока они не откроют один). xterm
в процессе, который он запрашивает для запуска вашей оболочки, обычно создается новый сеанс (и, следовательно, отсоединяется от терминала, с которого вы запустили, xterm
если есть), открывает новый, который /dev/pts/x
он породил, присоединяя это оконечное устройство к новому сеансу. Затем он выполнит вашу оболочку в этом процессе, поэтому ваша оболочка станет лидером сеанса. Ваша оболочка или любая интерактивная оболочка в этом сеансе, как правило, будет работать с группами процессов и tcsetpgrp()
для задания задних и фоновых заданий для этого терминала.
Что касается того, какая информация хранится на терминальном устройстве с дисциплиной tty (serial или pty) , это обычно то, что stty
команда отображает и изменяет. Все настройки дисциплины: размер экрана терминала, локальный, флаги ввода-вывода, настройки для специальных символов (например, ^ C, ^ Z ...), скорость ввода и вывода (не относится к ptys). Это соответствует функциям tcgetattr()
/, tcsetattr()
которые в Linux отображаются на TCGETS
/ TCSETS
ioctls, и TIOCGWINSZ
/ TIOCSWINSZ
для размера экрана. Вы можете утверждать, что текущая группа процессов переднего плана - это другая информация, хранящаяся в терминальном устройстве ( tcsetpgrp()
/ tcgetpgrp()
, TIOC{G,S}PGRP
ioctls), или текущий буфер ввода или вывода.
Обратите внимание, что информация о размере экрана, хранящаяся в терминальном устройстве, может не отражать реальность. Эмулятор терминала обычно устанавливает его (через тот же ioctl на основном размере), когда его окно изменяется, но он может выйти из синхронизации, если приложение вызывает ioctl на ведомой стороне или когда изменение размера не передается (в случае, если ssh-соединения, которое подразумевает создание другого pty, sshd
если ssh
игнорирует, SIGWINCH
например,). Некоторые терминалы также могут запрашивать свой размер с помощью escape-последовательностей, поэтому приложение может запрашивать его таким образом и обновлять дисциплину линии этой информацией.
Для получения более подробной информации вы можете, например, взглянуть на страницы man termios
и tty_ioctl
man в Debian.
Чтобы играть с другими дисциплинами линии:
Эмулируйте мышь псевдо-терминалом:
socat pty,link=mouse fifo:fifo
sudo inputattach -msc mouse # sets the MOUSE line discipline and specifies protocol
xinput list # see the new mouse there
exec 3<> fifo
printf '\207\12\0' >&3 # moves the cursor 10 pixels to the right
Выше главная сторона pty заканчивается socat на именованный канал ( fifo
). Мы подключаем эту fifo к процессу (оболочке), который записывает 0x87 0x0a 0x00, что в протоколе систем мыши означает no button pressed, delta(x,y) = (10,0)
. Здесь мы (оболочка) не эмулируем терминал, а мышь, 3 отправляемых нами байта не должны быть прочитаны (потенциально преобразованы) приложением из терминального устройства ( mouse
выше которого находится символическая ссылка, созданная socat
для некоторого /dev/pts/x
устройства) , но должны интерпретироваться как событие ввода мыши.
Создайте интерфейс SLIP:
# on hostA
socat tcp-listen:12345,reuseaddr pty,link=interface
# after connection from hostB:
sudo ldattach SLIP interface
ifconfig -a # see the new interface there
sudo ifconfig sl0 192.168.123.1/24
# on hostB
socat -v -x pty,link=interface tcp:hostA:12345
sudo ldattach SLIP interface
sudo ifconfig sl0 192.168.123.2/24
ping 192.168.123.1 # see the packets on socat output
Выше последовательный провод эмулируется socat
как сокет TCP между hostA и hostB. Дисциплина линии SLIP интерпретирует те байты, которыми обмениваются по этой виртуальной линии, как IP-пакеты, инкапсулированные SLIP, для доставки по sl0
интерфейсу.