Каковы обязанности каждого компонента псевдотерминала (PTY) (программное обеспечение, ведущая сторона, ведомая сторона)?


59

Я пытаюсь выяснить, как работает tty 1 (рабочий процесс и обязанности каждого элемента). Я прочитал несколько интересных статей об этом, но все еще есть некоторые размытые области.

Это то, что я понимаю до сих пор:

  • Эмулируемый терминал выполняет различные системные вызовы для /dev/ptmxглавной части псевдотерминала.
  • Основная часть псевдотерминала выделяет файл /dev/pts/[0-N], соответствующий устаревшему последовательному порту, и «присоединяет» к нему подчиненный псевдотерминал.
  • Подчиненный псевдотерминал хранит такую ​​информацию, как идентификатор сеанса, приоритетное задание, размер экрана.

Вот мои вопросы:

  1. Имеет ли ptmx какое-либо назначение помимо выделения подчиненной части? Предоставляет ли он какой-то «интеллект» , или эмулируемый терминал (например, xterm) обладает всеми интеллектуальными способностями вести себя как терминал?
  2. Почему xterm должен взаимодействовать с мастер-частью, поскольку он только перенаправляет stdout и stdin подчиненной части? Почему он не может напрямую писать и читать из файла pts ?
  3. Всегда ли идентификатор сессии прикрепляется к одному файлу pts и наоборот? Могу ли я набрать команду ps и найти 2 sessionId для того же / dev / pts / X ?
  4. Какую другую информацию ptsхранит магазин? Обновляет ли сам Xterm все поля самостоятельно или ptmдобавляет в него немного «интеллекта»?

1. Я основываю свое понимание на TTY, демистифицированном Линусом Акессоном , и на Linux Kernel постами Андриса Брауэра , как и на некоторых других вопросах на этих сайтах.

Ответы:


58

Терминальные эмуляторы

Главная сторона заменяет линию (пару проводов 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/ TCSETSioctls, и TIOCGWINSZ/ TIOCSWINSZдля размера экрана. Вы можете утверждать, что текущая группа процессов переднего плана - это другая информация, хранящаяся в терминальном устройстве ( tcsetpgrp()/ tcgetpgrp(), TIOC{G,S}PGRPioctls), или текущий буфер ввода или вывода.

Обратите внимание, что информация о размере экрана, хранящаяся в терминальном устройстве, может не отражать реальность. Эмулятор терминала обычно устанавливает его (через тот же ioctl на основном размере), когда его окно изменяется, но он может выйти из синхронизации, если приложение вызывает ioctl на ведомой стороне или когда изменение размера не передается (в случае, если ssh-соединения, которое подразумевает создание другого pty, sshdесли sshигнорирует, SIGWINCHнапример,). Некоторые терминалы также могут запрашивать свой размер с помощью escape-последовательностей, поэтому приложение может запрашивать его таким образом и обновлять дисциплину линии этой информацией.

Для получения более подробной информации вы можете, например, взглянуть на страницы man termiosи tty_ioctlman в Debian.

Чтобы играть с другими дисциплинами линии:

  1. Эмулируйте мышь псевдо-терминалом:

    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устройства) , но должны интерпретироваться как событие ввода мыши.

  2. Создайте интерфейс 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интерфейсу.


1
Это лучший ответ. Я отмечаю это как правильное и одобряю это. Можете ли вы добавить последнюю часть об информации, которая хранится в очках? Согласно этой странице (глава по настройке устройства TTY) , в pts хранятся такие значения, как количество строк и количество строк. Это какая-то другая информация, которую она хранит?
Пьер-Жан

@ Пьер-Жан, добавил больше информации.
Стефан Шазелас

Хотя ваш ответ намного выше удовлетворительного, было бы интересно увидеть более простой пример того, как вы на самом деле создаете / dev / pts / M. Я попытался с помощью cat /dev/ptmx &которого открывается новый pty, но затем я не могу найти связанный с ним процесс, так как бы вы его использовали? Во-вторых, я пытался echo "1" >/dev/ptmx, но это ничего не сделал ... Почему я заинтересован в этом? Часто, когда кто-то подключается удаленно через ssh(например), вы получаете PTY allocation request failedили No controlling tty: open /dev/ttyошибку, которая мешает управлению заданиями. Было бы неплохо лучше понять их.
not2qubit

@ user1147688, как создать pty было бы другим вопросом. Это уже слишком много вопросов одновременно. Но смотрите вашу ptyстраницу руководства для деталей.
Стефан Шазелас

@ StéphaneChazelas Небольшие уточнения: 1. То есть, вы говорите, что поток похож на physical term---- tty---- bashна терминалах и pty(m)---- tty---- pty(s)---- bashна эмуляторах терминалов? Была ли ttyдисциплина ответственна за отображение персонажей на физическом терминале? 2. Это программа эмулятора терминала, которая подключается к клавиатуре / экрану для управления вводом? 3. Согласно тому, что я понял, вы сказали, что буферизация строки команд bash / всего ввода терминала выполняется ttyдисциплиной строки вместо буферов ввода / вывода функций CI / O. Это верно?
форум

29

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


После долгих чтений я понял это.

  • Имеет ли ptmx какое-либо назначение помимо выделения подчиненной части? Предоставляет ли он какой-то «интеллект», или эмулируемый терминал (например, xterm) обладает всеми интеллектуальными способностями вести себя как терминал?

    /dev/ptmxне выделяет подчиненную часть : она выделяет «главную часть псевдотерминала». / dev / ptmx не является главным псевдотерминалом : это главный мультиплексор псевдотерминала . Он был создан с использованием стандарта Unix98 PTY, чтобы избежать условий гонки при выделении главного псевдотерминала ( источника ).

    Основная часть (ptm) псевдотерминала не представлена ​​в файловой системе. Он представлен дескриптором файла.

    Ведомая часть (PTS) представлена в файл , /dev/pts/Nгде Nэтого число.

    КОЗ получается из PTM через последовательный вызов grandpt, unlockpt, ptsname. ( Источник )

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

    Вот график того, что было TTY, подключенного к аппаратному устройству TTY связь с AUR

    А вот график tty, связанный с PTM TTY связь с PTM

    Файл ptm обрабатывает другие аргументы Ioctl (ISPTM, UNLKPT, TIOCREMOTE, TIOCSIGNAL), чем pts.

  • Почему xterm должен взаимодействовать с мастер-частью, поскольку он только перенаправляет stdout и stdin подчиненной части? Почему он не может напрямую писать и читать из файла pts?

    Процессы взаимодействуют с устройствами посредством действий, выполняемых с виртуальным файлом (чтение, запись, ioctl ...). Сам файл не существует, и драйвер использует файл для запуска действий при вызове методов чтения или записи. (См. Приложение для информации о водителях)

    TTY определяет точный способ взаимодействия с ним. Процессы пишут и читают с устройства и ожидают одинакового поведения независимо от того, какой тип TTY реализован.

    • функция чтения используется процессами для чтения записей с терминала
    • Функция записи используется процессами для отправки вывода на терминал

    Очки ведут себя как TTY-драйвер. Его метод чтения и записи используется для реализации поведения драйвера TTY. Поскольку реального устройства для отправки данных не существует, создается пара потоков, и ptm реализует функцию чтения для чтения данных, отправляемых pts в поток, и функцию записи для отправки данных в поток, который будет доступен когда оч его прочтет.

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

  • Всегда ли идентификатор сессии прикрепляется к одному файлу pts и наоборот? Могу ли я набрать команду ps и найти 2 sessionId для того же / dev / pts / X?

    Я так не думаю, идентификатор сессии определяется первым процессом, который присоединяет pts (обычно bash), и я не вижу способа создать другой сеанс и прикрепить его к тем же pts. Может быть, такой инструмент socatможет сделать это?

  • Какую другую информацию хранит pts? Обновляет ли сам Xterm все поля самостоятельно или ptm добавляет ему «интеллект»?

    Pts хранит 2 категории информации о терминале, с которым он связывается: the Terminfoи the Termcap. Обычно многие эмуляторы терминалов основаны на библиотеке, которая управляет для них информацией termcap (которая предоставит все значения возможностей, например, для эмуляции VTX100). Примером такой библиотеки является libvte . Редактировать (см. Комментарий Stephane Chazelas): возможности терминала не сохраняются очками.

пристройка


termcap и terminfo - это базы данных о возможностях терминала или эмулятора терминала, они не имеют никакого отношения к устройствам tty или pty.
Стефан Шазелас

Хорошо, я отредактирую свой ответ. Спасибо за комментарий. Можете ли вы добавить эту информацию о очках в свой ответ, если вы ее знаете (очевидно, в очках хранится размер экрана, например)?
Пьер-Жан

6
Это хорошие картинки. Какое программное обеспечение вы использовали для их создания?
Жиль "ТАК - перестань быть злым"

5
@ Жиль Спасибо. Я сделал это с Inkscape , редактором векторной графики с открытым исходным кодом. Возможно, это не самый эффективный способ сделать такую ​​графику, но если вам интересно, я написал статью о том, как создавать изометрические рисунки такого типа.
Пьер-Жан

Я не думаю, что вы когда-либо сможете подключить два сеанса к управляющему терминалу или позволить одному сеансу иметь более одного управляющего терминала
德里克 薯条 德里克

9

Вот схема, которую я сделал некоторое время назад о том, как sshdработает. Это не касается работы линейной дисциплины и прочего, но добавляет реальную иллюстрацию того, кто с чем взаимодействует:

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


Спасибо тебе большое за это. Я провел 2 дня, пытаясь понять это. Мне просто интересно, что происходит, когда не создается pty. stdin не существует, хорошо, но куда записываются stdout и stderr?
маленький чувак

@emmasculateur рад, что это помогло тебе. Извините, я не могу понять, что вы подразумеваете под "когда не создается pty". Можете ли вы привести пример, когда pty не создан?
Борис Бурков

1
Под термином «нет экземпляра pty» я подразумеваю, когда вы запускаете ssh -T, который, по словам человека, отключает выделение псевдотерминала. Например: ssh -T emasculateur@localhost "sleep 10" затем ps aux|grep sleepпоказывает это: emasculateur 21826 0.0 0.0 23032 3728 ? Ss 02:49 0:00 zsh -c sleep 10 В этом случае, где bash пишет stdoutи stderr? Я надеюсь, что мой вопрос имеет смысл.
маленький чувак

@emmasculateur Хм, это хороший вопрос, имеет смысл, я просто не думал об этом раньше. Я полагаю, что так, вы запускаете свой процесс в качестве демона на удаленной машине без связанного терминала. Я предполагаю, что его стандартный ввод / вывод / ошибка просто /dev/nullнравится обычному демону, но не уверен. Смотрите также: serverfault.com/questions/593399/…
Борис Бурков

@emmasculateur Я также наткнулся на случай, отличный от вашего: если у вашего процесса был терминал, но этот терминал был закрыт, процесс получал бы SIGHUP от ядра при попытке чтения / записи в stdout / stdin. Это часто убивает задания, запускаемые через ssh без nohupили screen/ tmux.
Борис Бурков

0

man pts говорит:

Файл / dev / ptmx - это символьный файл с большим номером 5 и вторым номером 2, обычно в режиме 0666 и владельцем. Группа root.root. Он используется для создания псевдотерминальной пары «ведущий и ведомый».

Когда процесс открывает / dev / ptmx, он получает дескриптор файла для главного устройства (PTM) псевдо-терминала, и в каталоге / dev / pts создается устройство псевдо-терминала (PTS). Каждый дескриптор файла, полученный открытием / dev / ptmx, является независимым PTM со своим собственным связанным PTS, путь которого можно найти, передав дескриптор ptsname (3).

Перед тем как открыть псевдо-терминал Slave, вы должны передать дескриптор файла мастера в grantpt (3) и unlockpt (3).

Как только главный и подчиненный псевдотерминалов открыты, подчиненный предоставляет процессам интерфейс, идентичный интерфейсу реального терминала.

Данные, записанные на ведомое устройство, представляются в главном дескрипторе как входные данные. Данные, записанные в ведущее устройство, представляются ведомому в качестве входных данных.

На практике псевдо-терминалы используются для реализации эмуляторов терминалов, таких как xterm (1), в которых данные, считываемые с главного устройства псевдо-терминала, интерпретируются приложением так же, как реальный терминал будет интерпретировать данные, и для реализации удаленных -логиновые программы, такие как sshd (8), в которых данные, считанные с главного устройства псевдо-терминала, отправляются по сети клиентской программе, подключенной к терминалу или эмулятору терминала.

Псевдотерминалы также можно использовать для отправки ввода программам, которые обычно отказываются считывать ввод из каналов (например, su (8) и passwd (8)).

О себе /dev/pts/X indexing:

каждый X это сеанс, который вы открываете, поэтому рабам нужно индексировать.

О TeteType (/dev/ttyN)

Это настоящая консоль была сгенерирована вашей загрузочной системой, такой как sysV.

О том, почему рабский хозяин заменил мастера: http://commons.wikimedia.org/wiki/File:Termios-script-diagram.png


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

SORRY ДЛЯ ПОЗЖЕ
Персидский залив

Чтобы использовать псевдо-TTY-подсистему, необходимо установить узел для главного драйвера / dev / ptmx и N подчиненных драйверов (N определяется при установке). Имена подчиненных устройств: / dev / pts / M, где M имеет значения от 0 до N-1. Пользователь получает доступ к псевдо-TTY-устройству через главное устройство (называемое ptm), к которому, в свою очередь, обращаются через драйвер клона. Главное устройство настроено как устройство-клон, где его основной номер устройства является основным для устройства-клона, а его младший номер устройства является основным для драйвера ptm.
Персидский залив

да, я читаю страницу человека пан! ....!
Персидский залив

это хорошая точка зрения: h20566.www2.hp.com/portal/site/hpsc/template.BINARYPORTLET/…
PersianGulf
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.