Quelles sont les responsabilités de chaque composant de pseudo-terminal (PTY) (logiciel, côté maître, côté esclave)?

59

J'essaie de comprendre le fonctionnement d'un terminal 1 (le flux de travail et les responsabilités de chaque élément). J'ai lu plusieurs articles intéressants à ce sujet, mais il y a encore des zones floues.

C'est ce que j'ai compris jusqu'à présent:

  • Le terminal émulé effectue différents appels système vers /dev/ptmxla partie principale du pseudo-terminal.
  • La partie maître du pseudo-terminal alloue un fichier /dev/pts/[0-N]correspondant au port série obsolète et y "attache" un pseudo-terminal esclave.
  • Le pseudo-terminal esclave conserve des informations telles que l'identifiant de session, le travail de premier plan, la taille de l'écran.

Voici mes questions:

  1. Ptmx a-t-il un intérêt autre que celui d'allouer la partie esclave? Fournit-il une sorte d’intelligence , ou le terminal émulé (xterm par exemple) a-t-il toute l’intelligence de se comporter comme un terminal?
  2. Pourquoi xterm doit-il interagir avec la partie master, car il ne fait que transmettre les sorties standard et stdin de la partie slave? Pourquoi ne peut-il pas directement écrire et lire à partir du fichier pts ?
  3. Un identifiant de session est-il toujours attaché à un fichier pts et inversement? Pourrais-je taper une commande ps et trouvé 2 sessionId pour le même / dev / pts / X ?
  4. Quelles autres informations le ptsmagasin? Xterm met-il à jour tous les champs par lui-même ou ptmajoute-t-il une "intelligence" dessus?

1. Je me base sur le TTY démystifié par Linus Akesson et sur le noyau Linux par Andries Brouwer , comme sur plusieurs autres questions sur ces sites.

Pierre Jean
la source

Réponses:

58

Émulateurs de terminaux

Le côté maître remplace la ligne (la paire de fils TX / RX) qui va au terminal.

Le terminal affiche les caractères qu’il reçoit sur l’un des fils (certains d’entre eux sont des caractères de contrôle et lui permettent de déplacer le curseur, de changer de couleur, etc.) et d’envoyer sur un autre fil les caractères correspondant aux touches que vous tapez.

Les émulateurs de terminaux tels que xterm ne sont pas différents, mais au lieu d’envoyer et de recevoir des caractères sur des câbles, ils lisent et écrivent des caractères sur leur descripteur de fichier côté maître. Une fois qu'ils ont créé le terminal esclave et démarré votre shell, ils ne le touchent plus. En plus d'émuler la paire de fils, xterm peut également modifier certaines propriétés de la discipline de ligne via ce descripteur de fichier du côté maître. Par exemple, ils peuvent mettre à jour les attributs de taille afin qu'un SIGWINCH soit envoyé aux applications qui interagissent avec l'esclave esclave pour les informer de la modification de leur taille.

Autre que cela, il y a peu d' intelligence dans l'émulateur terminal / terminal.

Ce que vous écrivez sur un terminal (comme l'esclave pty) correspond à ce que vous voulez lire, ce que vous lisez est ce que vous avez tapé là-bas, il est donc inutile que l'émulateur de terminal lise ou écrit dessus. . Ils sont ceux à l'autre bout.


La discipline de la ligne tty

Une grande partie de l' intelligence est dans la discipline de ligne tty . La discipline de ligne est un module logiciel (résidant dans le pilote, dans le noyau) poussé au-dessus d’un périphérique série / pty situé entre ce périphérique et la ligne / fil (le côté maître pour un pty).

Une ligne série peut avoir un terminal à l’autre extrémité, mais également une souris ou un autre ordinateur pour la mise en réseau. Vous pouvez, par exemple, associer une discipline de ligne SLIP pour obtenir une interface réseau sur un périphérique série (ou un périphérique pty), ou une discipline de ligne tty . La discipline de ligne tty est la discipline de ligne par défaut au moins sous Linux pour les périphériques série et pty. Sous Linux, vous pouvez changer la discipline de ligne avec ldattach.

Vous pouvez voir l’effet de désactiver la discipline de ligne tty en émettant stty raw -echo(notez que l’invite bash ou d’autres applications interactives, telles que vidéfinir le terminal dans le mode exact dont ils ont besoin, vous souhaitez donc utiliser une application idiote comme catcelle-ci). Ensuite, tout ce qui est écrit sur le terminal esclave est immédiatement lu par xterm du côté maître, et chaque caractère écrit par xterm sur le côté maître est immédiatement disponible pour la lecture sur le périphérique esclave.

La discipline de ligne est l'endroit où l'éditeur de ligne interne du terminal est implémenté. Par exemple , avec stty icanon echo(comme la valeur par défaut), lorsque vous tapez a, xterm écrit aau maître, puis la discipline ligne échos en arrière (fait un adisponible pour la lecture par l' xtermaffichage), mais ne fait rien disponible pour la lecture sur le côté esclave . Ensuite, si vous tapez backspace, xterm envoie un caractère ^?ou ^H, la discipline de ligne (telle que ^?ou ^Hcorrespondant au eraseparamètre de discipline de ligne) renvoie au maître a ^H, spaceet ^Hpour xtermeffacer leavous venez de taper sur son écran et n'envoyez toujours rien à l'application qui lit le côté esclave, il met simplement à jour son tampon d'éditeur de lignes interne pour supprimer ce que avous avez déjà tapé.

Ensuite, lorsque vous appuyez sur Entrée, xterm envoie ^M(CR), que la discipline de ligne convertit en entrée en ^ J (LF), et envoie ce que vous avez entré jusqu'à présent pour être lu du côté esclave (une application lisant dessus /dev/pts/xrecevra ce vous avez tapé en incluant le LF, mais pas le adepuis que vous l'avez supprimé), tandis que du côté maître, il envoie un CR et un LF pour déplacer le curseur à la ligne suivante et au début de l'écran.

La discipline de ligne est également responsable de l’ envoi du SIGINTsignal au groupe de processus de premier plan du terminal lorsqu’il reçoit un ^Ccaractère du côté maître, etc.

De nombreuses applications de terminaux interactifs désactivent la plupart des fonctionnalités de cette discipline de ligne pour les implémenter elles-mêmes. Mais dans tous les cas, sachez que le terminal ( xterm) a peu d’implication dans cette tâche (à part l’affichage de ce qu’il est dit d'afficher).

Et il ne peut y avoir qu'une seule session par processus et par terminal. Un terminal de contrôle peut être associé à une session sans que cela soit nécessaire (toutes les sessions démarrent sans terminal jusqu'à ce qu'elles en ouvrent un). xtermDans le processus qu’il demande à exécuter votre shell créera généralement une nouvelle session (et par conséquent se détachera du terminal à partir duquel vous avez été lancé le xtermcas échéant), ouvrez la nouvelle création /dev/pts/xqu’il a engendrée, en reliant ce périphérique terminal à la nouvelle session. Il exécutera ensuite votre shell dans ce processus, de sorte que votre shell deviendra le leader de la session. Votre shell ou tout shell interactif de cette session jonglera généralement avec les groupes de processus et tcsetpgrp(), pour définir les tâches de premier plan et d’arrière-plan pour ce terminal.

Quant aux informations stockées par un terminal avec une discipline tty (série ou pty) , c'est généralement ce que la sttycommande affiche et modifie. Toute la configuration de la discipline: taille de l’écran du terminal, local, indicateurs de sortie, réglages des caractères spéciaux (comme ^ C, ^ Z ...), vitesse d’entrée et de sortie (non pertinent pour les ptys). Cela correspond aux fonctions tcgetattr()/ tcsetattr()qui sous Linux correspondent aux TCGETS/ TCSETSioctls et TIOCGWINSZ/ TIOCSWINSZpour la taille de l'écran. Vous pouvez faire valoir que le groupe de processus de premier plan actuel est une autre information stockée dans le périphérique terminal ( tcsetpgrp()/ tcgetpgrp(), TIOC{G,S}PGRPioctls) ou dans le tampon d’entrée ou de sortie actuel.

Notez que les informations de taille d'écran stockées dans le terminal peuvent ne pas refléter la réalité. L’émulateur de terminal le définit généralement (via le même ioctl sur la taille du maître) lorsque sa fenêtre est redimensionnée, mais il peut se désynchroniser si une application appelle ioctl du côté esclave ou si le redimensionnement n’est pas transmis (en cas d’une connexion ssh qui implique un autre pty engendré par sshdif sshignore SIGWINCHpar exemple). Certains terminaux peuvent également être interrogés sur leur taille via des séquences d'échappement. Ainsi, une application peut l'interroger de cette manière et mettre à jour la discipline de ligne avec ces informations.

Pour plus de détails, vous pouvez consulter les pages de manuel termioset tty_ioctlde Debian, par exemple.

Pour jouer avec d'autres disciplines de la ligne:

  1. Émulez une souris avec un pseudo-terminal:

    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
    

    Ci-dessus, le côté maître du lot est terminé par socat sur un pipe nommé ( fifo). Nous connectons ce fifo à un processus (le shell) qui écrit 0x87 0x0a 0x00, ce qui signifie dans le protocole du système de souris no button pressed, delta(x,y) = (10,0). Ici, nous (le shell) n'émulons pas un terminal, mais une souris, les 3 octets que nous envoyons ne doivent pas être lus (potentiellement transformés) par une application du périphérique terminal ( mousece qui est un lien symbolique créé par socatun /dev/pts/xpériphérique). , mais doivent être interprétés comme un événement d’entrée de la souris.

  2. Créez une interface 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
    

    Ci-dessus, le fil série est émulé par socatun socket TCP entre hostA et hostB. La discipline de ligne SLIP interprète les octets échangés sur cette ligne virtuelle en tant que paquets IP encapsulés SLIP pour livraison sur l' sl0interface.

Stéphane Chazelas
la source
1
C'est la meilleure réponse. Je le marque comme étant juste et je le vote. Pouvez-vous ajouter la dernière partie sur les informations que pts magasins? Selon cette page (chapitre Configuration du dispositif TTY) , les points stockent des valeurs telles que le nombre de lignes et le nombre de lignes. Sont-ils d'autres informations qu'il stocke?
Pierre-Jean
@ Pierre-Jean, a ajouté plus d'informations.
Stéphane Chazelas
Bien que votre réponse soit bien satisfaisante, il serait intéressant de voir un exemple plus simple sur la manière dont vous créez réellement un fichier / dev / pts / M. J'ai essayé d'utiliser cat /dev/ptmx &qui ouvre un nouveau pty, mais alors il n'y a aucun processus que je puisse trouver associé, alors comment l'utiliseriez-vous? Deuxièmement, j'ai essayé avec echo "1" >/dev/ptmx, mais cela n'a rien fait ... Pourquoi m'intéresse-t-il? Beacause souvent quand on se connecte à distance via ssh(par exemple), vous obtenez PTY allocation request failedou No controlling tty: open /dev/ttyerreur, ce qui empêche le contrôle de l' emploi. Ce serait bien de mieux les comprendre.
not2qubit
@ user1147688, comment créer un pty serait une question différente. Celui-ci est déjà trop de questions à la fois. Mais consultez votre ptypage de manuel pour plus de détails.
Stéphane Chazelas
@ StéphaneChazelas Petites précisions: 1. Vous dites donc que le flux est comme physical term---- tty---- bashsur les terminaux et pty(m)---- tty---- pty(s)---- bashsur les émulateurs de terminaux? La ttydiscipline était-elle également responsable de l' écho des personnages sur le terminal physique? 2. Est-ce le programme d'émulateur de terminal qui se connecte au clavier / à l'écran pour gérer les entrées? 3. D'après ce que j'ai compris, vous avez dit que la mise en mémoire tampon des commandes bash / toutes les entrées du terminal est effectuée par ttydiscipline de ligne au lieu des mémoires tampon d'E / S des fonctions CI / O. Est-ce correct?
forumulateur
29

Edit: Depuis cette réponse, j’ai écrit un article sur mon blog, à l’intention des personnes intéressées par plus de détails.


Après beaucoup de lecture, c'est ce que j'ai compris.

  • Ptmx a-t-il un intérêt autre que celui d'allouer la partie esclave? Fournit-il une sorte d’intelligence ou le terminal émulé (xterm par exemple) a-t-il toute l’intelligence de se comporter comme un terminal?

    /dev/ptmxn'alloue pas la partie esclave : il alloue la "partie maître du pseudo terminal". / dev / ptmx n’est pas le pseudo-terminal maître : c’est un multiplexeur maître de pseudo-terminaux . Il a été créé avec le standard Unix98 PTY pour éviter les situations de concurrence lors de l’allocation du pseudo-terminal maître ( source ).

    La partie principale (ptm) du pseudo-terminal n'est pas représentée sur le système de fichiers. Il est représenté par un descripteur de fichier.

    La partie esclave (pts) est représentée par un fichier /dev/pts/NNest un nombre.

    Les points sont obtenues à partir du PTM par l'appel successif de grandpt, unlockpt, ptsname. ( Source )

    Le ptm remplace le pilote AUR dédié à la communication avec le périphérique et l'édition en ligne. Ainsi, il n'émule en aucune manière un terminal mais fournit la fonctionnalité d' édition en ligne , et fournit un moyen de visualiser et de communiquer avec les pts. ( Source )

    Voici un graphique de ce qu'était un téléscripteur connecté à un périphérique matériel Communication TTY avec AUR

    Et voici un graphique d’un terminal connecté à un ptm Communication TTY avec PTM

    Le fichier ptm gère différents arguments Ioctl (ISPTM, UNLKPT, TIOCREMOTE, TIOCSIGNAL) par rapport aux pts.

  • Pourquoi xterm doit-il interagir avec la partie master, car il ne fait que transmettre les sorties standard et stdin de la partie slave? Pourquoi ne peut-il pas directement écrire et lire à partir du fichier pts?

    Les processus interagissent avec les périphériques via des actions effectuées sur un fichier virtuel (lecture, écriture, ioctl ..). Le fichier lui-même n'existe pas et le pilote utilise ce fichier pour déclencher des actions lorsque des méthodes de lecture ou d'écriture sont appelées. (Voir l'annexe pour plus d'informations sur les pilotes)

    Un téléscripteur définit un moyen précis d'interagir avec lui. Les processus écrivent et lisent à partir du périphérique et attendent le même comportement, quel que soit le type de TTY mis en œuvre.

    • la fonction read est utilisée par les processus pour lire les entrées du terminal
    • la fonction write est utilisée par les processus pour envoyer une sortie au terminal

    Les pts se comportent comme un pilote TTY. Ses méthodes de lecture et d'écriture sont utilisées pour implémenter le comportement du pilote TTY. Comme il n’existe pas de périphérique réel pour l’envoi des données, une paire de flux est créée et ptm implémente une fonction de lecture pour lire les données envoyées par les pts au flux et une fonction d’écriture pour envoyer les données au flux qui sera disponible. quand les pts le liront.

    Rappelez-vous que le fichier représentant un périphérique n'est pas un fichier classique et que, s'il xtermveut voir ce qui a été écrit dans le fichier, il ne peut pas simplement s'appeler ouvrir et le lire, car ces fonctions ont ici un comportement complètement différent.

  • Un identifiant de session est-il toujours attaché à un fichier pts et vice versa? Pourrais-je taper une commande ps et trouvé 2 sessionId pour le même / dev / pts / X?

    Je ne pense pas, l'id de session est défini par le premier processus qui attache les pts (bash en général), et je ne vois pas de moyen de créer une autre session et de l'attacher aux mêmes pts. Peut-être qu'un outil comme celui-ci socatpourrait faire ça?

  • Quelles autres informations les pts stockent-ils? Xterm met-il à jour tous les champs lui-même ou le gestionnaire de projet ajoute-t-il une "intelligence" dessus?

    Les pts stockent 2 catégories d’informations concernant le terminal avec lequel il communique: le Terminfoet le Termcap. Généralement, de nombreux émulateurs de terminaux sont basés sur des bibliothèques qui gèrent les informations termcap pour eux (qui fourniront toutes les valeurs de capacités pour émuler un VTX100, par exemple). Un exemple d'une telle bibliothèque est libvte . Edit (voir le commentaire Stephane Chazelas): Les capacités du terminal ne sont pas stockées par les pts.

Annexe

Pierre Jean
la source
termcap et terminfo sont des bases de données sur les capacités d'un terminal ou d'un émulateur de terminal. Elles n'ont rien à voir avec les périphériques tty ou pty.
Stéphane Chazelas
Ok, je vais modifier ma réponse. Merci pour le commentaire. Pouvez-vous ajouter cette information sur les pts à votre réponse si vous la connaissez (apparemment, pts stocke la taille de l'écran, par exemple)?
Pierre-Jean
6
Ce sont de belles images. Quel logiciel avez-vous utilisé pour les fabriquer?
Gilles, arrête de faire le mal
5
@ Gilles Merci. Je les ai réalisées avec Inkscape , un éditeur de graphiques vectoriels à code source ouvert. Ce n'est peut-être pas la manière la plus efficace de faire ce genre de graphisme, mais si cela vous intéresse, j'ai écrit un article sur la création de ce type de dessins isométriques.
Pierre-Jean
Je ne pense pas que vous pouvez jamais attch deux sessions à un terminal de contrôle ou de laisser une session ont plus d'un terminal de contrôle
炸鱼薯条德里克
9

Voici un schéma que j'ai fait il y a quelque temps sur la façon dont sshdfonctionne. Cela ne concerne pas le fonctionnement de la discipline de ligne et autres, mais ajoute une illustration réelle de qui interagit avec quoi:

entrez la description de l'image ici

Boris Burkov
la source
Merci beaucoup pour ça. J'ai passé 2 jours à essayer de comprendre. Je me demande simplement ce qui se passe quand aucun pty n'est instancié. stdin n'existe pas, d'accord, mais où sont écrits stdout et stderr?
petit-mec
@emmasculateur content de t'avoir aidé. Désolé, je ne comprends pas ce que vous entendez par "quand aucun pty n'est instancié". Pouvez-vous donner un exemple de quand pty n'est pas instancié?
Boris Burkov
1
Par "aucun pty n'est instancié" je veux dire quand vous exécutez ssh avec -T, l'homme dit qu'il désactive l'allocation de pseudo-terminal. Par exemple: montre ssh -T emasculateur@localhost "sleep 10" ensuite ps aux|grep sleepceci: emasculateur 21826 0.0 0.0 23032 3728 ? Ss 02:49 0:00 zsh -c sleep 10 Dans ce cas, où bash écrit-il stdoutet stderr? J'espère que ma question a un sens.
petit-mec
@ emmasculateur hm, c'est une bonne question, ça a du sens, je n'y avais pas pensé plus tôt. J'imagine que c'est ainsi que vous démarrez votre processus en tant que démon sur une machine distante, sans terminal associé. Mon hypothèse est que son entrée / sortie / erreur standard va /dev/nullcomme pour un démon normal, mais pas sûr. Voir aussi: serverfault.com/questions/593399/…
Boris Burkov
@emmasculateur Je suis également tombé sur un cas différent du vôtre: si votre processus avait un terminal, mais que ce terminal était fermé, le processus recevrait SIGHUP du noyau lors de la tentative de lecture / écriture de stdout / stdin. Cela tue souvent les travaux, démarrés via ssh sans nohupou screen/ tmux.
Boris Burkov
0

man pts dit:

Le fichier / dev / ptmx est un fichier de caractères numéroté 5 et 2, généralement du mode 0666 et du fichier owner.group de root.root. Il est utilisé pour créer un couple pseudo-terminal maître / esclave.

Lorsqu'un processus ouvre / dev / ptmx, il obtient un descripteur de fichier pour un maître pseudo-terminal (PTM) et un périphérique pseudo-terminal esclave (PTS) est créé dans le répertoire / dev / pts. Chaque descripteur de fichier obtenu en ouvrant / dev / ptmx est un PTM indépendant avec son propre PTS associé, dont le chemin peut être trouvé en passant le descripteur à ptsname (3).

Avant d'ouvrir le pseudo-terminal esclave, vous devez transmettre le descripteur de fichier du maître à grantpt (3) et unlocklock (3).

Une fois que le pseudo-terminal maître et l'esclave sont ouverts, l'esclave fournit aux processus une interface identique à celle d'un terminal réel.

Les données écrites sur l'esclave sont présentées en entrée sur le descripteur de maître. Les données écrites sur le maître sont présentées à l'esclave en tant qu'entrée.

En pratique, les pseudo-terminaux sont utilisés pour la mise en oeuvre d'émulateurs de terminaux tels que xterm (1), dans lesquels les données lues dans le maître du pseudo-terminal sont interprétées par l'application de la même manière qu'un terminal réel interpréterait les données, et pour la mise en oeuvre à distance. programmes de connexion tels que sshd (8), dans lesquels les données lues à partir du maître de pseudo-terminal sont envoyées sur le réseau à un programme client connecté à un terminal ou à un émulateur de terminal.

Les pseudo-terminaux peuvent également être utilisés pour envoyer des entrées à des programmes qui refusent normalement de lire des entrées à partir de tubes (tels que su (8) et passwd (8)).

À propos de /dev/pts/X indexing:

chaque X est une session que vous ouvrez, les esclaves doivent donc indexer.

À propos de TeteType (/dev/ttyN):

C'est la vraie console a été générée par votre système de démarrage tel que sysV.

Pourquoi esclave insted of master: http://commons.wikimedia.org/wiki/File:Termios-script-diagram.png

Golfe Persique
la source
Je suis désolé, mais vous n'avez pas répondu aux questions. J'ai déjà lu la page de manuel et vu ce graphique, mais le comportement n'était pas clair. Pouvez-vous, comme le suggère illuminÉ, étendre votre réponse en fonction des questions?
Pierre-Jean
DÉSOLÉ POUR TARD
Golf Persian
Pour utiliser le sous-système pseudo-TTY, vous devez installer un nœud pour le pilote côté maître / dev / ptmx et le nombre N de pilotes esclaves (le nombre N est déterminé lors de l'installation). Les noms des périphériques esclaves sont / dev / pts / M, où M a les valeurs 0 à N-1. Un utilisateur accède à un pseudo-téléscripteur via le périphérique maître (appelé ptm), lequel est accessible via le pilote de clonage. Le périphérique maître est configuré en tant que périphérique clone, son numéro majeur étant numéro de périphérique mineur est le majeur pour le pilote ptm.
PersianGulf
oui j'ai lu man pan page ....!
PersianGulf