¿Cuáles son las responsabilidades de cada componente Pseudo-Terminal (PTY) (software, lado maestro, lado esclavo)?


59

Estoy tratando de descubrir cómo funciona un tty 1 (el flujo de trabajo y las responsabilidades de cada elemento). He leído varios artículos interesantes al respecto, pero todavía hay algunas áreas borrosas.

Esto es lo que entiendo hasta ahora:

  • El terminal emulado realiza diferentes llamadas al sistema /dev/ptmx, la parte maestra del pseudo-terminal.
  • La parte maestra del pseudo terminal asigna un archivo /dev/pts/[0-N], correspondiente al puerto serie obsoleto, y "adjunta" un pseudo terminal esclavo al mismo.
  • El pseudo terminal esclavo guarda información como el ID de sesión, el trabajo en primer plano, el tamaño de la pantalla.

Aquí están mis preguntas:

  1. ¿Tiene ptmx algún propósito además de asignar la parte esclava? ¿Proporciona algún tipo de "inteligencia" , o el terminal emulado (xterm por ejemplo) tiene toda la inteligencia de comportarse como un terminal?
  2. ¿Por qué xterm tiene que interactuar con la parte maestra, ya que solo reenvía el stdout y stdin de la parte esclava? ¿Por qué no puede escribir y leer directamente desde el archivo pts ?
  3. ¿Se adjunta siempre una ID de sesión a un archivo pts y viceversa? ¿Podría escribir un comando ps y encontré 2 sessionId para el mismo / dev / pts / X ?
  4. ¿Qué otra información tiene la ptstienda? ¿Xterm actualiza todos los campos por sí mismo o ptmagrega alguna "inteligencia"?

1. Baso mi comprensión en el TTY desmitificado por Linus Akesson , y el kernel de Linux por las publicaciones de Andries Brouwer , como en varias otras preguntas en estos sitios

Respuestas:


58

Emuladores de terminal

El lado maestro reemplaza la línea (el par de cables TX / RX) que va al terminal.

El terminal muestra los caracteres que recibe en uno de los cables (algunos de ellos son caracteres de control y hacen que haga cosas como mover el cursor, cambiar el color ...) y envía en otro cable los caracteres correspondientes a las teclas que escribe.

Los emuladores de terminal como xterm no son diferentes, excepto que en lugar de enviar y recibir caracteres en los cables, leen y escriben caracteres en su descriptor de archivo en el lado maestro. Una vez que han generado la terminal esclava, y comenzaron su shell en eso, ya no tocan eso. Además de emular el par de cables, xterm también puede cambiar algunas de las propiedades de disciplina de línea a través del descriptor de archivo al lado maestro. Por ejemplo, pueden actualizar los atributos de tamaño para que se envíe un SIGWINCH a las aplicaciones que interactúan con el esclavo pty para notificarles sobre un tamaño cambiado.

Aparte de eso, hay poca inteligencia en el emulador de terminal / terminal.

Lo que escribe en un dispositivo terminal (como el pty slave) es lo que quiere decir que se mostrará allí, lo que lee de él es lo que ha escrito allí, por lo que no tiene sentido que el emulador de terminal lea o escriba en eso . Ellos son los del otro extremo.


La disciplina de la línea tty

Mucha de la inteligencia está en la disciplina de la línea tty . La disciplina de línea es un módulo de software (que reside en el controlador, en el núcleo) empujado encima de un dispositivo serial / pty que se encuentra entre ese dispositivo y la línea / cable (el lado maestro para un pty).

Una línea en serie puede tener un terminal en el otro extremo, pero también un mouse u otra computadora para la conexión en red. Puede adjuntar una disciplina de línea SLIP, por ejemplo, para obtener una interfaz de red en la parte superior de un dispositivo serie (o dispositivo pty), o puede tener una disciplina de línea tty . La disciplina de línea tty es la disciplina de línea predeterminada al menos en Linux para dispositivos seriales y pty. En Linux, puede cambiar la disciplina de línea con ldattach.

Puede ver el efecto de deshabilitar la disciplina de línea tty emitiendo stty raw -echo(tenga en cuenta que el indicador bash u otras aplicaciones interactivas como viconfigurar el terminal en el modo exacto que necesitan, por lo que desea utilizar una aplicación tonta como catpara experimentar con eso). Luego, todo lo que se escribe en el dispositivo terminal esclavo llega inmediatamente al lado maestro para que xterm lo lea, y cada carácter escrito por xterm en el lado maestro está inmediatamente disponible para leer desde el dispositivo esclavo.

La disciplina de línea es donde se implementa el editor de línea interno del dispositivo terminal . Por ejemplo, con stty icanon echo(como es el valor predeterminado), cuando escribe a, xterm escribe aen el maestro, luego la disciplina de línea lo repite (lo pone a adisposición para leerlo xtermpara mostrarlo), pero no pone a disposición nada para leer en el lado esclavo . Luego, si escribe retroceso, xterm envía un carácter ^?o ^H, la disciplina de línea (como eso ^?o ^Hcorresponde a la eraseconfiguración de disciplina de línea) vuelve a enviar al maestro a ^H, spacey ^Hpara xtermborrar elaacaba de escribir en su pantalla y todavía no envía nada a la aplicación que lee desde el lado esclavo, solo actualiza su búfer interno del editor de línea para eliminar lo que aha escrito anteriormente.

Luego, cuando presiona Enter, xterm envía ^M(CR), que la disciplina de línea convierte en entrada a a ^ J (LF), y envía lo que ha ingresado hasta ahora para leer en el lado esclavo (una aplicación de lectura /dev/pts/xrecibirá lo que ha escrito incluyendo LF, pero no adesde que lo ha eliminado), mientras que en el lado maestro, envía un CR y LF para mover el cursor a la siguiente línea y al inicio de la pantalla.

La disciplina de línea también es responsable de enviar la SIGINTseñal al grupo de procesos en primer plano del terminal cuando recibe un ^Ccarácter en el lado maestro, etc.

Muchas aplicaciones de terminal interactivas deshabilitan la mayoría de las características de esa disciplina de línea para implementarlas ellos mismos. Pero en cualquier caso, tenga en cuenta que el terminal ( xterm) tiene poca participación en eso (excepto mostrar lo que se le dice que muestre).

Y solo puede haber una sesión por proceso y por dispositivo terminal. Una sesión puede tener un terminal de control conectado pero no tiene que hacerlo (todas las sesiones comienzan sin un terminal hasta que abren uno). xterm, en el proceso en el que se bifurca para ejecutar su shell, generalmente creará una nueva sesión (y, por lo tanto, se desconectará del terminal desde el que lo inició xterm), abra el nuevo /dev/pts/xque ha generado, al conectar ese dispositivo terminal a la nueva sesión. Luego ejecutará su shell en ese proceso, por lo que su shell se convertirá en el líder de la sesión. Su shell o cualquier shell interactivo en esa sesión generalmente hará malabarismos con los grupos de procesos y tcsetpgrp(), para establecer los trabajos en primer plano y en segundo plano para ese terminal.

En cuanto a qué información almacena un dispositivo terminal con una disciplina tty (serial o pty) , eso es lo que el sttycomando muestra y modifica. Toda la configuración de disciplina: tamaño de la pantalla del terminal, local, indicadores de salida de entrada, configuraciones para caracteres especiales (como ^ C, ^ Z ...), velocidad de entrada y salida (no relevante para ptys). Eso corresponde a las funciones tcgetattr()/ tcsetattr()que en Linux se asignan a TCGETS/ TCSETSioctls, y TIOCGWINSZ/ TIOCSWINSZpara el tamaño de la pantalla. Puede argumentar que el grupo de proceso en primer plano actual es otra información almacenada en el dispositivo terminal ( tcsetpgrp()/ tcgetpgrp(), TIOC{G,S}PGRPioctls), o el búfer de entrada o salida actual.

Tenga en cuenta que la información del tamaño de la pantalla almacenada en el dispositivo terminal puede no reflejar la realidad. El emulador de terminal generalmente lo configurará (a través del mismo ioctl en el tamaño maestro) cuando se cambie el tamaño de su ventana, pero puede salir de la sincronización si una aplicación llama al ioctl en el lado esclavo o cuando el cambio de tamaño no se transmite (en caso de una conexión ssh que implica otra pty generada por sshdsi sshignora el SIGWINCHpor ejemplo). Algunos terminales también pueden consultar su tamaño a través de secuencias de escape, por lo que una aplicación puede consultarlo de esa manera y actualizar la disciplina de línea con esa información.

Para más detalles, se puede echar un vistazo a la termiosy tty_ioctlpáginas de manual en Debian, por ejemplo.

Para jugar con otras disciplinas de línea:

  1. Emule un mouse con 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
    

    Arriba, el lado maestro de la pty es terminado por socat en una tubería con nombre ( fifo). Conectamos ese fifo a un proceso (el shell) que escribe 0x87 0x0a 0x00 que en el protocolo del sistema del mouse significa no button pressed, delta(x,y) = (10,0). Aquí, nosotros (el shell) no estamos emulando un terminal, sino un mouse, los 3 bytes que enviamos no deben ser leídos (potencialmente transformados) por una aplicación desde el dispositivo terminal ( mousearriba del cual hay un enlace simbólico hecho por socatalgún /dev/pts/xdispositivo) , pero deben interpretarse como un evento de entrada del mouse.

  2. Crear una interfaz 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
    

    Arriba, el cable serie se emula socatcomo un socket TCP entre hostA y hostB. La disciplina de línea SLIP interpreta los bytes intercambiados a través de esa línea virtual como paquetes IP encapsulados SLIP para su entrega en la sl0interfaz.


1
Esta es la mejor respuesta. Lo marco como correcto y lo voté. ¿Puedes agregar la última parte sobre información que pts almacena? De acuerdo con esta página (capítulo de configuración del dispositivo TTY) , los pts almacenan valores como el número de filas y el número de líneas. ¿Hay alguna otra información que almacena?
Pierre-Jean

@ Pierre-Jean, agregó más información.
Stéphane Chazelas

Aunque su respuesta es más que satisfactoria, sería interesante ver un ejemplo más simple sobre cómo crear realmente un / dev / pts / M. Intenté usar el cat /dev/ptmx &que abre una nueva pty, pero no hay ningún proceso que pueda encontrar asociado con él, entonces, ¿cómo lo usarías? Lo intenté en segundo lugar echo "1" >/dev/ptmx, pero eso no hizo nada ... ¿Por qué estoy interesado en esto? Pd a menudo cuando uno se conecta de forma remota a través de ssh(por ejemplo), se obtiene PTY allocation request failedo No controlling tty: open /dev/ttyde error, lo que impide el control de trabajos. Sería bueno entenderlos mejor.
not2qubit

@ user1147688, cómo crear una pty sería una pregunta diferente. Esta ya es demasiadas preguntas a la vez. Pero vea su ptypágina de manual para más detalles.
Stéphane Chazelas

@ StéphaneChazelas Pequeñas aclaraciones: 1. ¿Entonces está diciendo que el flujo es como physical term---- tty---- bashen terminales y pty(m)---- tty---- pty(s)---- bashen emuladores de terminales? ¿Fue la ttydisciplina responsable de hacer eco de los caracteres en la terminal física también? 2. ¿Es el programa emulador de terminal el que se conecta al teclado / pantalla para administrar la entrada? 3. De acuerdo con lo que entendí, usted dijo que el almacenamiento en línea de los comandos bash / toda la entrada del terminal se realiza mediante ttydisciplina de línea en lugar de los almacenamientos intermedios de E / S de las funciones de CI / O. ¿Es esto correcto?
forumulator

29

Editar: desde esta respuesta, escribí un artículo dedicado en mi blog, para las personas que estarían interesadas en obtener más detalles.


Después de mucha lectura, esto es lo que entendí.

  • ¿Tiene ptmx algún propósito además de asignar la parte esclava? ¿Proporciona algún tipo de "inteligencia", o el terminal emulado (xterm por ejemplo) tiene toda la inteligencia de comportarse como un terminal?

    /dev/ptmxno asigna la parte esclava : asigna la "parte maestra pseudo terminal". / dev / ptmx no es el pseudo terminal maestro : es un multiplexor maestro pseudo terminal . Se ha creado con el estándar Unix98 PTY para evitar condiciones de carrera al asignar un pseudo terminal maestro ( fuente ).

    La parte maestra (ptm) del pseudo terminal no está representada en el sistema de archivos. Está representado por un descriptor de archivo.

    La parte esclava (pts) está representada por un archivo en /dev/pts/Ndonde Nhay un número.

    Los pts se obtiene de la PTM a través de la llamada sucesiva de grandpt, unlockpt, ptsname. ( Fuente )

    El ptm reemplaza el controlador AUR dedicado a comunicarse con el dispositivo y la edición de línea. Por lo tanto, no emula de ninguna manera un terminal, sino que proporciona la función de edición de línea y proporciona una forma de visualizar y comunicarse con pts. ( Fuente )

    Aquí hay un gráfico de lo que era un TTY conectado a un dispositivo de hardware Comunicación TTY con AUR

    Y aquí hay un gráfico de un tty conectado a un ptm Comunicación TTY con PTM

    El archivo ptm maneja diferentes argumentos Ioctl (ISPTM, UNLKPT, TIOCREMOTE, TIOCSIGNAL) que los pts.

  • ¿Por qué xterm tiene que interactuar con la parte maestra, ya que solo reenvía el stdout y stdin de la parte esclava? ¿Por qué no puede escribir y leer directamente desde el archivo pts?

    Los procesos interactúan con los dispositivos a través de acciones realizadas en un archivo virtual (lectura, escritura, ioctl ..). El archivo en sí no existe y el controlador lo utiliza para activar acciones cuando se llama a los métodos de lectura o escritura. (Ver Anexo para información sobre conductores)

    Un TTY define una forma precisa de interactuar con él. Los procesos escriben y leen desde el dispositivo y esperan el mismo comportamiento independientemente de qué tipo de TTY se implemente.

    • La función de lectura es utilizada por los procesos para leer entradas desde el terminal
    • La función de escritura es utilizada por los procesos para enviar la salida al terminal

    Los pts se comportan como un controlador TTY. Su método de lectura y escritura se utiliza para implementar el comportamiento del controlador TTY. Como no hay un dispositivo real para enviar los datos, se crea un par de secuencias y el ptm implementa una función de lectura para leer los datos que envían los pts a la secuencia, y una función de escritura para enviar datos a la secuencia que estará disponible cuando los pts lo leerán.

    Recuerde, el archivo que representa un dispositivo no es un archivo clásico, y si xtermquiere ver lo que se ha escrito en el archivo, no puede simplemente abrirlo y leerlo, ya que estas funciones tienen un comportamiento completamente diferente aquí.

  • ¿Se ha adjuntado siempre una ID de sesión a un archivo pts y viceversa? ¿Podría escribir un comando ps y encontré 2 sessionId para el mismo / dev / pts / X?

    No lo creo, el ID de sesión se define por el primer proceso que adjunta los pts (bash en general), y no veo una manera de crear otra sesión y adjuntarla a los mismos pts. Tal vez una herramienta como socatpodría hacer esto?

  • ¿Qué otra información almacena el pts? ¿Xterm actualiza todos los campos por sí mismo o el ptm agrega alguna "inteligencia"?

    Los pts almacenan 2 categorías de información sobre el terminal con el que se está comunicando: el Terminfoy el Termcap. Por lo general, muchos emuladores de terminal se basan en una biblioteca que administra la información de captación de términos para ellos (que proporcionará todos los valores de capacidades para emular un VTX100, por ejemplo). Un ejemplo de dicha biblioteca es libvte . Editar (consulte el comentario de Stephane Chazelas): los pts no almacenan las capacidades del terminal.

Anexo


termcap y terminfo son bases de datos sobre capacidades de terminal o emulador de terminal, no tienen nada que ver con dispositivos tty o pty.
Stéphane Chazelas

Ok, editaré mi respuesta. Gracias por el comentario. ¿Puede agregar esta información sobre pts en su respuesta si la conoce (aparentemente pts almacena el tamaño de la pantalla, por ejemplo)?
Pierre-Jean

66
Estas son buenas imágenes. ¿Qué software usaste para hacerlos?
Gilles 'SO- deja de ser malvado'

55
@Gilles Gracias. Los hice con Inkscape , un editor de gráficos vectoriales de código abierto. Quizás no sea la forma más eficiente de hacer este tipo de gráficos, pero si está interesado, escribí un artículo sobre cómo crear este tipo de dibujos isométricos.
Pierre-Jean

No creo que pueda conectar dos sesiones a una terminal de control o dejar que una sesión tenga más de una terminal de control
炸鱼 薯条 德里克

9

Aquí hay un esquema que hice hace algún tiempo sobre cómo sshdfunciona. No se refiere al funcionamiento de la disciplina de línea y otras cosas, pero agrega una ilustración de la vida real de quién interactúa con qué:

ingrese la descripción de la imagen aquí


muchas gracias por esto. Pasé 2 días tratando de resolverlo. Me pregunto qué sucede cuando no se crea una instancia de piedad. stdin no existe, bien, pero ¿dónde se escriben stdout y stderr?
pequeño amigo

@emmasculateur me alegra que te haya ayudado. Lo siento, no puedo entender lo que quieres decir con "cuando no se crea una instancia de piedad". ¿Puedes dar un ejemplo de cuándo pty no se instancia?
Boris Burkov

1
Por "no se crea una instancia de pty" quiero decir cuando ejecuta ssh with -T, que el hombre dice que desactiva la asignación de pseudo terminales. por ejemplo: ssh -T emasculateur@localhost "sleep 10" luego ps aux|grep sleepmuestra esto: emasculateur 21826 0.0 0.0 23032 3728 ? Ss 02:49 0:00 zsh -c sleep 10 en ese caso, ¿dónde escribe bash stdouty stderr? Espero que mi pregunta tenga sentido.
pequeño amigo

@emmasculateur hm, es una buena pregunta, tiene sentido, simplemente no lo pensé antes. Supongo que esa es la manera, comienzas tu proceso como un demonio en una máquina remota, sin terminal asociada. Supongo que su entrada / salida / error estándar simplemente va a /dev/nullgustar para un demonio normal, pero no estoy seguro. Ver también: serverfault.com/questions/593399/…
Boris Burkov

@emmasculateur También me topé con un caso diferente al suyo: si su proceso solía tener terminal, pero ese terminal estaba cerrado, el proceso recibiría SIGHUP desde el núcleo al intentar leer / escribir stdout / stdin. Esto a menudo mata los trabajos, comenzados a través de ssh sin nohupo screen/ tmux.
Boris Burkov

0

man pts dice:

El archivo / dev / ptmx es un archivo de caracteres con el número mayor 5 y el número menor 2, generalmente del modo 0666 y el grupo de propietarios de root.root. Se utiliza para crear un par maestro y esclavo pseudo-terminal.

Cuando un proceso abre / dev / ptmx, obtiene un descriptor de archivo para un maestro pseudo-terminal (PTM), y se crea un dispositivo esclavo pseudo-terminal (PTS) en el directorio / dev / pts. Cada descriptor de archivo obtenido al abrir / dev / ptmx es un PTM independiente con su propio PTS asociado, cuya ruta se puede encontrar pasando el descriptor a ptsname (3).

Antes de abrir el esclavo pseudo-terminal, debe pasar el descriptor de archivo del maestro a grantpt (3) y unlockpt (3).

Una vez que el maestro y el esclavo pseudo-terminal están abiertos, el esclavo proporciona procesos con una interfaz que es idéntica a la de un terminal real.

Los datos escritos en el esclavo se presentan en el descriptor maestro como entrada. Los datos escritos en el maestro se presentan al esclavo como entrada.

En la práctica, los pseudo-terminales se utilizan para implementar emuladores de terminal como xterm (1), en el que la aplicación interpreta los datos leídos del maestro pseudo-terminal de la misma manera que un terminal real interpretaría los datos, y para implementar -Iniciar sesión programas como sshd (8), en el que los datos leídos del maestro pseudo-terminal se envían a través de la red a un programa cliente que está conectado a un terminal o emulador de terminal.

Los pseudo terminales también se pueden usar para enviar entradas a programas que normalmente se niegan a leer entradas de tuberías (como su (8) y passwd (8)).

Acerca de /dev/pts/X indexing:

cada X es una sesión que se abre, por lo que los esclavos necesitan indexar.

Acerca de TeteType (/dev/ttyN):

Su consola real ha sido generada por su sistema de arranque como sysV.

Acerca de por qué esclavo insted de maestro: http://commons.wikimedia.org/wiki/File:Termios-script-diagram.png


Lo siento, pero no respondiste a las preguntas. Ya leí la página de manual y vi este gráfico, pero el comportamiento no estaba claro. ¿Puede usted, como sugiere illuminÉ, extender su respuesta de acuerdo con las preguntas?
Pierre-Jean

LO SENTIMOS PARA TARDE
PersianGulf

Para usar el subsistema pseudo-TTY, debe instalarse un nodo para el controlador del lado maestro / dev / ptmx y N número de controladores esclavos (se determina N en la instalación). Los nombres de los dispositivos esclavos son / dev / pts / M donde M tiene los valores de 0 a N-1. Un usuario accede a un dispositivo pseudo-TTY a través del dispositivo maestro (llamado ptm) al que a su vez se accede a través del controlador de clonación. El dispositivo maestro se configura como un dispositivo de clonación donde su número de dispositivo principal es el principal para el dispositivo de clonación y su El número de dispositivo menor es el mayor para el controlador ptm.
PersianGulf

sí, leí la página de pan del hombre ...
PersianGulf

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.