El subsistema TTY , o abstracción TTY , es una de las bases de los sistemas operativos Unix o similares a Unix, en particular Linux . Este sistema está diseñado para el uso de una terminal por varios procesos, algunas posibilidades de entrada (por ejemplo, enviar señales con teclas especiales, borrar caracteres ingresados).
Funciones como cambiar el color de los caracteres y el fondo, cambiar el estilo de los caracteres, mover el cursor dependen del programa de emulación o del controlador de terminal. Por lo general , se utilizan secuencias de escape ANSI para implementarlas .
En 1869, se inventó el teletipo , una máquina de telégrafo especial para transmitir cotizaciones de valores . Gradualmente, este dispositivo se convirtió en el teletipo , un dispositivo más rápido basado en la tabla de caracteres ASCII . En un momento, los teletipos de todo el mundo incluso se conectaron en una sola red llamada Telex , en la que el direccionamiento se realizaba según el mismo principio de un eje giratorio con buscadores que en las centrales telefónicas automáticas mecánicas de esa época. La red Telex se utilizó para transmitir telegramas comerciales. Sin embargo, los teletipos aún no estaban conectados a las computadoras en ese momento .
En la década de 1960, las computadoras eran capaces de realizar múltiples tareas al mismo tiempo . En particular, se ha hecho posible la interacción en tiempo real entre una computadora y un usuario . Cuando el modelo de procesamiento de trabajos por lotes heredado fue reemplazado por la interfaz de línea de comandos , los teletipos comenzaron a usarse como dispositivos de entrada y salida , ya que ya estaban disponibles en el mercado.
Dado que había muchos modelos diferentes de teletipos, se requería un cierto nivel de compatibilidad de software para abstraerse de un modelo particular de teletipo. En los sistemas UNIX y similares a UNIX , la operación de bajo nivel del teletipo, por ejemplo, el número de bits por paquete, la tasa de baudios , el control de flujo , la paridad , los códigos especiales para el formateo de página rudimentario, etc., se dejaba al operador . núcleo del sistema . Las funciones como el movimiento del cursor , el texto en color, etc., solo se hicieron posibles a fines de la década de 1970 , con la llegada de terminales de video como el VT-100 . Todas estas funciones avanzadas quedaron en manos de las aplicaciones .
Con el mayor desarrollo de las computadoras, los teletipos y luego las terminales de video se convirtieron en cosa del pasado. Sin embargo, los subsistemas para trabajar con ellos, aunque sufrieron cambios significativos, permanecieron en los núcleos de los sistemas operativos.
Digamos que el usuario está escribiendo en un teletipo y la computadora está imprimiendo la respuesta. El teletipo se utiliza como un terminal físico (real) . Se conecta a una computadora mediante un puerto serie asíncrono universal . El sistema operativo tiene un controlador de puerto que se encarga de la transferencia física de bytes (paridad, control de flujo, etc.). En el caso más simple, este controlador simplemente puede pasar datos a la aplicación que lo usa. Sin embargo, las siguientes funciones no estarán disponibles:
Implica la posibilidad de borrar caracteres impresos. De acuerdo con la filosofía de UNIX , los programas deben mantenerse lo más simples posible , por lo que esta funcionalidad la proporciona el controlador del kernel, no el programa de teletipo. El sistema operativo proporciona un búfer para editar texto, así como algunos comandos de edición simples: "eliminar carácter", "eliminar palabra", "eliminar línea". Todas estas funciones están implementadas en el módulo de disciplina de línea . Están habilitados por defecto ; este modo se llama canónico, o cocido (cocido). El programa, si lo desea, puede deshabilitar estas funciones cambiando el controlador al modo sin procesar (sin procesar). (La mayoría de los programas de consola interactiva ( editores de texto , agentes de correo , shells y todos los programas que usan Curses o Readline ) se ejecutan en modo sin procesar y manejan todos los comandos de edición por sí mismos). La capa de protocolo mencionada también le permite configurar eco (visualización de caracteres escritos en el mismo terminal), conversión automática de signos de fin de línea y retorno de carro , etc. Por lo tanto, la capa de protocolo es un analizador de texto primitivo como Sed , y trabajando en modo kernel .
El punto de separar el procesamiento descrito anteriormente en una capa separada es que la disciplina (es decir, el controlador específico de esta capa) se puede cambiar dinámicamente . Por ejemplo, en lugar de una disciplina de terminal, puede activar la disciplina de comunicación de datos por conmutación de paquetes : ppp , IrDA , mouse en serie , etc.
Como regla general, el usuario quiere ejecutar varios programas al mismo tiempo e interactuar con ellos a su vez. Si el programa se congela , el usuario probablemente querrá bloquearsesu. Los procesos que se ejecutan en segundo plano deberían bloquearse tan pronto como quieran mostrar algún texto en la pantalla. Del mismo modo, el texto escrito por el usuario solo debe transmitirse al programa actualmente activo . El sistema operativo implementa todas estas funciones utilizando el controlador TTY.
Tanto la capa de disciplina (protocolo) como el controlador TTY son pasivos . En otras palabras, no pueden realizar ninguna acción por sí mismos, sino que son solo un conjunto de procedimientos que pueden ser llamados por otros procedimientos. En cambio, el propio sistema operativo es un proceso , es decir, tiene su propio contexto .
Un sistema de un controlador de puerto UART, una disciplina (protocolo) y un controlador TTY se denomina dispositivo TTY , o simplemente TTY . Un proceso de usuario puede cambiar el comportamiento de cualquier dispositivo TTY manipulando su archivo correspondienteen la carpeta /dev . Naturalmente, para ello, este proceso debe tener permisos de escritura.a este archivo. Entonces, cuando el usuario inicia sesióny se conecta a un TTY específico, ese usuario debe convertirse en propietario del archivo correspondiente a ese TTY. Esto es exactamente lo que hace el programa de inicio de sesión . (El propio programa de inicio de sesión se ejecuta como superusuario ).
Ahora considere el caso cuando el sistema se está ejecutando en una computadora personal ordinaria y moderna . La disciplina y el controlador TTY funcionan igual que antes, pero el controlador del puerto UART ya no está, ya que no hay un teletipo que se conecte a través de él. En su lugar, se utiliza un emulador de terminal de video , un programa que imita una terminal de video (similar a un teletipo, pero con una pantalla de video en lugar de una cinta de papel) y muestra el contenido de esta terminal en la pantalla. Al mismo tiempo, este programa, a diferencia de la consola , ya se está ejecutando en el espacio del usuario., en lugar del núcleo, que proporciona mucha más flexibilidad; por ejemplo, puede mostrar una terminal en una ventana , como lo hace Xterm .
Para permitir el funcionamiento de un emulador de terminal en el espacio del usuario, y al mismo tiempo no abandonar todo el subsistema TTY descrito anteriormente, se inventó el llamado pseudo-terminal, o PTY. Un pseudo-terminal se puede ejecutar dentro de otro pseudo-terminal; esto es lo que hacen Screen o el cliente Ssh , por ejemplo .
Un emulador de terminal gráfico, como xterm por ejemplo, primero crea un nuevo pseudo-terminal y un proceso secundario que se convierte en el líder de la nueva sesión, convierte al esclavo del pseudo-terminal en su terminal de control y lanza un intérprete de comandos (la mayoría a menudo bash o sh). El emulador de terminal utiliza la parte maestra del pseudoterminal para mostrar los datos recibidos de la parte esclava. Todos los procesos iniciados desde el intérprete, incluido el propio intérprete, realizan entrada ( stdin ) y salida ( stdout y stderr ) a través del esclavo.
Hay dos API disponibles en Linux para crear una pseudo terminal ( pty(7)): UNIX 98 ( pts(4)) y BSD. [una]
La primera opción es abrir un archivo /dev/ptmx(se recomienda usar int posix_openpt(int flags)), que vinculará el descriptor de archivo devuelto al host y /dev/pts/creará un nuevo archivo esclavo en el directorio con un nombre entero positivo. Cada apertura de este archivo crea un nuevo pseudo-terminal. Para conocer la ruta exacta a la parte accionada, existe una función char* ptsname(int fd). Antes de abrir la parte conducida, debe llamar grantpty unlockpt.
En el caso de BSD, /dev/hay muchos archivos de la forma ttyXY(seguidor) y ptyXY(líder) en el directorio.
En este ejemplo, usando el comando ps l, puede ver el estado de cada proceso, y la columna WCHAN mostrará el evento que está esperando un proceso de suspensión en particular.
$ pdl F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIEMPO COMANDO 0 500 5942 5928 15 0 12916 1460 esperar Ss pts/14 0:00 -/bin/bash 0 500 12235 5942 15 0 21004 3572 esperar S+ pts/14 0:01 vim index.php 0 500 12580 12235 15 0 8080 1440 esperar S+ pts/14 0:00 /bin/bash -c (ps l) >/tmp/v727757/1 2>&1 0 500 12581 12580 15 0 4412 824 - R+ pts/14 0:00 ps lLa columna STAT en la salida del comando ps muestra el estado del proceso, pero también puede contener varios indicadores:
Son estos atributos los que se utilizan para el control del trabajo . El trabajo del controlador TTY es realizar un seguimiento del ID del grupo de proceso activo (que el proceso maestro de la sesión actualiza explícitamente).
Las siguientes señales están directamente relacionadas con TTY:
SUSCRÍBETE El controlador de puerto UART envía una señal SIGHUP para toda la sesión cuando el módem pasa al estado colgado. Esto generalmente mata todos los procesos en la sesión. Algunos programas, como Screen o Nohup , se separan de su sesión y su TTY para que sus procesos secundarios no mueran cuando se desconecta el módem. SEGUIR El controlador TTY genera la señal SIGINT cuando ^Caparece un carácter especial (el código ASCII de este carácter es 3) en el flujo de entrada. El controlador envía esta señal al trabajo activo. Un programa que tenga acceso al TTY puede cambiar el código de este carácter especial o deshabilitar la generación de esta señal por completo. El administrador de sesión realiza un seguimiento de la configuración de TTY establecida por cada una de las tareas en ejecución y las aplica cuando esas tareas cambian. SIGQUITAR Similar a SIGINT, carácter especial para generar: ^\. TUBO DE SEÑAL Esta señal es útil en trabajos porque permite que la construcción yes | headde tipo finalice el proceso sí cuando finaliza el proceso principal. SIGCHLD El núcleo envía una señal SIGCHLD a un proceso cuando uno de sus procesos secundarios muere o cambia de estado. Junto con la señal SIGCHLD, waitpidpuede usarla para obtener información adicional, como el proceso y los ID de usuario, el código de retorno (o la señal que provocó el bloqueo). Con la ayuda de esta señal, el proceso anfitrión de la sesión monitorea la ejecución de sus tareas. SEGUIMIENTO Esta señal suspende la ejecución del proceso que la recibe. Solo el proceso init puede procesarlo . Normalmente, el núcleo no utiliza esta señal. En su lugar, el carácter especial ^Zenvía una señal SIGTSTP, que ya puede ser capturada por la aplicación; como regla general, la aplicación realiza ciertas acciones, después de lo cual se detiene, ya con una señal SIGSTOP. SIGCONT Esta señal despierta el proceso previamente puesto a dormir. Lo envía el shell cuando el usuario emite un comando fg. Dado que esta señal no se puede manejar, una señal SIGCONT inesperada indica que el proceso se suspendió y luego se despertó. SIGTSTP SIGTSTP es similar a SIGINT y SIGQUIT. Carácter especial ^Z( código ASCII 26). SIGTTIN Cuando un proceso que se ejecuta en segundo plano intenta leer desde un TTY, el TTY envía esta señal a todo el trabajo. Esto normalmente suspende el trabajo hasta que el usuario cambia a él y puede ingresar los datos esperados. SIGTTU Similar al anterior, pero llamado cuando un proceso en segundo plano intenta escribir en un TTY. Esta señal de este TTY se puede desactivar. SIGWINCH El TTY envía una señal SIGWINCH al trabajo activo cuando cambia el tamaño del terminal.Considere el siguiente ejemplo. Deje que el usuario edite el texto en un editor de texto de la consola. El cursor está aproximadamente en el medio de la pantalla y el editor está ocupado realizando una tarea que requiere mucho tiempo de CPU (por ejemplo, buscar y reemplazar palabras en un archivo grande). En este punto, el usuario presiona ^Z.
Si la disciplina (protocolo de enlace) se configuró para interceptar este carácter, el usuario no tendría que esperar a que el editor completara el trabajo actual, porque la capa de disciplina enviaría inmediatamente una señal SIGTSTP a la tarea activa (es decir, el proceso activo). grupo). Además, este grupo incluye no solo el editor en sí, sino también todos sus procesos secundarios.
Deje que el editor configure el manejo manual de la señal SIGTSTP. Luego, el kernel llama al controlador de interrupciones (dentro del proceso del editor de texto). Este controlador mueve el cursor a la última línea de la pantalla escribiendo una secuencia específica de caracteres de control en el TTY. Dado que el editor es un proceso activo, estos caracteres se transfieren y procesan inmediatamente. Luego, el editor se envía a sí mismo (ya su grupo de procesos) una señal SIGSTOP y se duerme.
El hecho de que el editor de texto se haya dormido se señala al proceso maestro de la sesión con la señal SIGCHLD (junto con los ID de los procesos dormidos). Cuando todos los procesos de la tarea activa se suspenden, el líder de la sesión recuerda la configuración actual de TTY y se declara a sí mismo como la tarea activa de ese TTY con la llamada al sistema ioctl. Luego imprime una notificación al usuario en la pantalla de que la tarea actual ha sido suspendida.
Si el comando se llama ahora ps, mostrará que el editor de texto está en pausa (letra "T"). Si intenta activarlo, por ejemplo, con un comando integrado de shell bgo killenviándole una señal SIGCONT, el editor ejecutará el controlador de señal SIGCONT. Este controlador intentará volver a dibujar la interfaz escribiendo una secuencia de caracteres de control en el TTY. Sin embargo, ahora el editor es un proceso en segundo plano, por lo que en lugar de renderizar la interfaz, TTY enviará una señal SIGTTOU al editor y se quedará dormido nuevamente. El proceso anfitrión de la sesión lo sabrá con la señal SIGCHLD y volverá a mostrar una notificación al usuario.
Si se invoca el comando en su lugar, el fgshell restaurará la configuración de TTY guardada anteriormente, volverá a hacer que el editor sea la tarea activa y le enviará (y a su grupo de procesos) una señal SIGCONT. Después de eso, el editor podrá dibujar su interfaz normalmente y el trabajo continuará.
Puede averiguar el TTY que administra un programa de shell dado usando la utilidad tty.
Un TTY abierto se puede configurar con ioctl. Sin embargo, esta interfaz no es portátil , por lo que se recomienda utilizar contenedores compatibles con POSIX en su lugar (ver man 3 termios).
TTY también se puede configurar directamente desde la consola usando una utilidad sttyque se basa en la API termios mencionada anteriormente :
$ orzuelo -a velocidad 38400 baudios; filas 73; columnas 238; línea=0; intr = ^C; salir = ^\; borrar = ^?; matar = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; cambiar=<undef>; inicio = ^Q; parada = ^S; susp = ^Z; imprimir = ^R; erase = ^W; siguiente = ^V; rubor = ^O; mín = 1; tiempo = 0; -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany imaxbel -iutf8 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig iconon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echokestty -amuestra todas las configuraciones de TTY. Se puede seleccionar un TTY específico usando la bandera -F.
speedmuestra la velocidad del puerto UART. Los pseudo terminales ignoran este valor.
rowsy columnsmostrar el tamaño del terminal en caracteres. De hecho, estas son solo dos variables numéricas dentro del controlador TTY que se pueden leer y modificar libremente. Cuando cambien, se enviará una señal SIGWINCH a la tarea activa.
linemuestra el número de la disciplina activa. Todas las disciplinas disponibles en el sistema se enumeran en /proc/tty/ldiscs.
Los caracteres especiales se enumeran a continuación, seguidos de las opciones actualmente seleccionadas. Un guión significa que la opción está deshabilitada.
Si abre una ventana de Xterm, recuerde su TTY (llamando al comando tty) y el tamaño (llamando al comando stty -a), inicie una aplicación de consola de pantalla completa (como vim ) y luego escriba otra ventana de Xterm stty -F X rows Y, donde X es el TTY el nombre de la primera ventana, y Y es la mitad de su altura, entonces vim recibirá inmediatamente una señal SIGWINCH en la primera ventana y volverá a dibujar su interfaz usando solo la mitad de la ventana que se le proporcionó.
Si escribe en la ventana Xterm stty intr o, ahora se generará la señal SIGINT cuando escriba el carácter "o". En este caso, presionar ^Cno conducirá a nada.
A veces, el botón de retroceso no funciona en un sistema UNIX . Esto se debe a que el emulador de terminal está enviando un código ASCII diferente al TTY que el asignado a la función en ese TTY erase. Para resolver este problema, debe escribir stty erase ^Ho stty erase ^?. El primer comando establecerá el carácter de borrado en el código ASCII 8, el segundo en 127. Las aplicaciones que se ejecutan en modo sin procesar no se ven afectadas por esta configuración.
Escribir en una ventana de Xterm stty -icanondesactivará el modo canónico. Si después de eso intenta, por ejemplo, ejecutar el programa cat , todos los atajos de teclado responsables de editar texto, como ^Uo incluso la tecla de retroceso, no funcionarán. Además, catrecibirá (y, en consecuencia, emitirá) datos no en líneas, como antes, sino en caracteres separados.
Si escribe en una ventana Xterm stty -echo, esto deshabilitará la visualización de los datos que escribe. Llamar al programa después de esto catdemostrará que los datos escritos en el teclado ya no se muestran en la pantalla (es decir, tendrá que escribir el texto "a ciegas"). Sin embargo, después de presionar la tecla Enter, el kernel pasará la última línea impresa al programa cat, y ya la mostrará en la pantalla.
Escribir en una ventana de Xterm stty -tostoppermitirá que los procesos que se ejecutan en segundo plano escriban en la pantalla en lugar de bloquearse. Por ejemplo, el comando (sleep 5; echo hello, world) &mostrará un indicador de shell, pero después de 5 segundos, la línea se mostrará en la consola «hello, world». Si en este momento trabaja con el terminal (por ejemplo, escribe algún texto), entonces esta línea encajará directamente en este texto escrito. Si escribe stty tostop, ejecutar el comando (sleep 5; echo hello, world) &bloqueará este proceso con una señal SIGTTOU, porque después de 5 segundos intentará mostrar texto en segundo plano. Por lo general, el shell en tales casos muestra un mensaje de advertencia (ya sea inmediatamente o en el siguiente aviso).
El comando stty sanedevuelve la configuración de TTY a parámetros "sanos".
Se puede encontrar más información en el sistema (info libc, "Control de trabajos"). info