¿Qué relaciones hay entre mi terminal de control actual y `/dev/tty`?

¿Qué relaciones hay entre mi terminal de control actual y `/dev/tty`?

En Lubuntu 18.04, ejecuto un shell en lxterminal. Su terminal de control es el pseudoterminal esclavo actual:

$ tty
/dev/pts/2

Me gustaría saber qué relaciones hay entre mi terminal de control actual /dev/pts/2y /dev/tty.

  1. /dev/ttyactúa como mi terminal de control actual /dev/pts/2:

    $ echo hello > /dev/tty
    hello
    
    $ cat < /dev/tty
    world
    world
    ^C
    
  2. Pero parecen ser archivos no relacionados, en lugar de que uno sea un enlace simbólico o un enlace físico al otro:

    $ ls -lai /dev/tty /dev/pts/2
     5 crw--w---- 1 t    tty 136, 2 May 31 16:38 /dev/pts/2
    13 crw-rw-rw- 1 root tty   5, 0 May 31 16:36 /dev/tty
    

Para diferentes sesiones con diferentes terminales de control, se /dev/ttygarantiza que serán sus terminales de control. ¿Cómo pueden ser diferentes terminales de control, sin ser un enlace simbólico o un enlace físico?

¿Cuáles son entonces sus relaciones y diferencias? ¡Cualquier ayuda es muy apreciada!

Esta publicación se originó a partir de una anterior.¿La salida del comando `tty` y el archivo `/dev/tty` se refieren a la terminal de control del proceso bash actual?

Respuesta1

La ttypágina de manual en la sección 4afirma lo siguiente:

El archivo/desarrollo/ttyes un archivo de caracteres con número mayor 5 y número menor 0, generalmente de modo 0666 y propietario.grupo raíz.tty. Es sinónimo de terminal controlador de un proceso, si lo hay.

Además deioctl(2)solicitudes admitidas por el dispositivo al que se refiere tty, elioctl(2)TIOCNOTTYSe admite la solicitud .

TIOCNOTTY

Separe el proceso de llamada de su terminal de control.

Si el proceso es el líder de la sesión, entonces se SIGHUPenvían SIGCONTseñales al grupo de procesos de primer plano y todos los procesos en la sesión actual pierden su tty de control.

Esteioctl(2)La llamada funciona solo en descriptores de archivos conectados a /desarrollo/tty. Lo utilizan los procesos demonio cuando son invocados por un usuario en una terminal. El proceso intenta abrir/desarrollo/tty. Si la apertura tiene éxito, se desconecta del terminal usando TIOCNOTTY, mientras que si la apertura falla, obviamente no está conectado a un terminal y no necesita desconectarse.

Esto explicaría en parte por qué /dev/ttyno hay un enlace simbólico al terminal de control: admitiría un ioctl, y podría no haber un terminal de control (pero un proceso siempre puede intentar acceder /dev/tty). Sin embargo, la documentación es incorrecta: ioctlno solo se puede acceder al adicionala través de /dev/tty(verla respuesta de mosvy, que también da una explicación más sensata de la naturaleza de /dev/tty).

/dev/ttypuede representar diferentes terminales de control, sin ser un enlace, porque el controlador que lo implementa determina cuál es el terminal de control del proceso que llama, si lo hay.

Puede pensar en esto como /dev/ttysi fuera el terminal de control y, por lo tanto, ofrece una funcionalidad que solo tiene sentido para un terminal de control, mientras que /dev/pts/2etc. son terminales simples, uno de los cuales podría ser el terminal de control de un proceso determinado.

Respuesta2

/dev/ttyes un dispositivo de carácter "mágico" que, cuando se abre, devolverá un identificador al terminal actual.

Suponiendo que el terminal de control es /dev/pts/1, un descriptor de archivo abierto mediante /dev/pts/1y uno abierto mediante /dev/ttyse referirán al mismo dispositivo; cualquier operación de escritura, lectura u otra operación de archivo funcionará igual en cualquiera de ellos.

En particular, aceptarán el mismo conjunto de ioctls y TIOCNOTTYno es un ioctl adicional que solo esté disponible a través de/dev/tty.

ioctl(fd, TIOCNOTTY)funciona igual en cualquier descriptor de archivo que haga referencia a una terminal, siempre que sea la terminal controladora del proceso que lo llama.

No importa si el descriptor se obtuvo abriendo /dev/tty, /dev/pts/1, /dev/ptmx(en cuyo caso el ioctl actuará sobre su correspondienteesclavo), o más recientemente, mediante una llamada a ioctl(master, TIOCGPTPEER, flags).

Ejemplo:

$ cat <<'EOT' >tiocnotty.c
#include <sys/ioctl.h>
#include <unistd.h>
#include <err.h>

int main(int ac, char **av){
        if(ioctl(0, TIOCNOTTY)) err(1, "io(TIOCNOTTY)");
        if(ac < 2) return 0;
        execvp(av[1], av + 1);
        err(1, "execvp %s", av[1]);
}
EOT
$ cc -W -Wall tiocnotty.c -o tiocnotty
$ ./tiocnotty
$ ./tiocnotty </dev/tty
$ tty
/dev/pts/0
$ ./tiocnotty </dev/pts/0

Además, en realidad no "separará" el proceso actual del tty; el proceso aún podrá leerlo, un botón ^Cen el terminal lo eliminará, etc. Su único efecto en un proceso que no es líder de sesión es que ya no se podrá acceder al tty a través de /dev/tty, y ya no será aparece como el tty controlador en /proc/PID/stat:

$ ./tiocnotty cat
^C
$ ./tiocnotty cat
^Z
[2]+  Stopped                 ./tiocnotty cat
$ ./tiocnotty cat
foo
foo
^D
$ ./tiocnotty cat /dev/tty
cat: /dev/tty: No such device or address
$ ./tiocnotty awk '{print$7}' /proc/self/stat
0

[el séptimo campo /proc/<pid>/states la identificación del dispositivo del tty controlador, consulte proc(5)]

Si el proceso que lo llama es el líder de la sesión, realmente separará la sesión del tty y enviará un par SIGHUP/ SIGCONTal grupo de procesos de primer plano de la sesión. Pero incluso entonces, el terminalnose cerrará y el proceso aún podrá leerlo, si sobrevive a SIGHUP:

$ script /dev/null -c 'trap "" HUP; exec ./tiocnotty cat'
Script started, file is /dev/null
lol
lol
^C^C^C^C^C  # no controlling tty anymore

wtf  
wtf
^D   # but still reading fine from it
Script done, file is /dev/null

/dev/ttyno es un enlace simbólico como /dev/stdin=> /dev/fd/0=> /proc/self/fd/0=> /dev/pts/0porque se inventó mucho antes que los sistemas de archivos dinámicos virtuales como procfs (y mucho antes que los enlaces simbólicos en general). Y muchos programas han llegado a depender de su semántica particular (por ejemplo, /dev/ttyfallar ENODEVcuando el terminal de control no es accesible).

información relacionada