2009-09-17 18 views
12

Echo un vistazo al código de la utilidad 'menos', específicamente cómo se ingresa el teclado. Curiosamente, en la línea 80 de ttyin.c, establece el descriptor de archivo a leer:Less recibe entrada de teclado de stderr?

 /* 
     * Try /dev/tty. 
     * If that doesn't work, use file descriptor 2, 
     * which in Unix is usually attached to the screen, 
     * but also usually lets you read from the keyboard. 
     */ 
    #if OS2 
     /* The __open() system call translates "/dev/tty" to "con". */ 
     tty = __open("/dev/tty", OPEN_READ); 
    #else 
     tty = open("/dev/tty", OPEN_READ); 
    #endif 
     if (tty < 0) 
      tty = 2; 

no es el archivo descriptor de 2 stderr? Si es así, ¿WTH? Pensé que la entrada del teclado se envió a través de stdin.

Curiosamente, incluso si lo hace ls -l * | less, después de que el archivo termina de cargar, aún puede utilizar el teclado para desplazarse hacia arriba y hacia abajo, pero si lo hace ls -l * | vi, a continuación, VI gritarte porque no lee de la entrada estándar . ¿Cúal es la gran idea? ¿Cómo terminé en esta nueva tierra extraña donde stderr es tanto una manera de informar errores a la pantalla y leer desde el teclado? No creo estar en Kansas nunca más ...

+0

Por cierto, si escribe 'ls -l * | vim -', vim realizará una magia similar. – ephemient

Respuesta

19
 
$ ls -l /dev/fd/ 
lrwx------ 1 me me 64 2009-09-17 16:52 0 -> /dev/pts/4 
lrwx------ 1 me me 64 2009-09-17 16:52 1 -> /dev/pts/4 
lrwx------ 1 me me 64 2009-09-17 16:52 2 -> /dev/pts/4 

Cuando se haya identificado en una terminal interactiva, los tres descriptores de archivos estándar apuntan a lo mismo: su TTY (o pseudo-TTY).

 
$ ls -fl /dev/std{in,out,err} 
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdin -> fd/0 
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdout -> fd/1 
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stderr -> fd/2 

Por convención, leemos de 0 y escribir en 1 y 2. Sin embargo, nada nos impide hacer lo contrario.

Cuando el shell ejecuta ls -l * | less, se crea un tubo de ls 's descriptor de archivo 1 a less' s descriptor de archivo 0. Obviamente, less ya no puede leer la entrada del teclado del usuario desde el descriptor de archivo 0 – que intenta recuperar el TTY como le sea posible.

Si no se ha extraído less, open("/dev/tty") le dará el TTY.

Sin embargo, en caso de que falle ... ¿qué puedes hacer? less hace un último intento de obtener el TTY, suponiendo que el descriptor de archivo 2 se adjunta a la misma que se adjuntaría el descriptor de archivo 0, si no se redirigiera.

Este no es prueba de fallos:

 
$ ls -l * | setsid less 2>/dev/null 

Aquí, less se da su propia sesión (lo que ya no es una parte del grupo de proceso activo del terminal, provocando open("/dev/tty") a fallar), y su archivo El descriptor 2 se ha cambiado – ahora less sale inmediatamente, porque está saliendo a un TTY pero no recibe ninguna entrada del usuario.

+3

+1, muy completo. –

+0

Oh, lo veo ahora. Debido a que stderr no es más que un descriptor de archivo que está realmente conectado a la terminal, puede leer o escribir a voluntad. ¡ESO ES GENIAL! Gracias, emocionante. – Michael

+0

No se archivaría el descriptor '2' ¿solo estaría abierto para escribir? –

2

Bueno ... primero parece que falta la llamada open() que abre '/ dev/tty'. Solo utiliza el descriptor de archivo 2 si la llamada a open() falla. En un sistema Linux estándar, y probablemente en muchos Unices, '/ dev/tty' existe y es poco probable que cause un error.

En segundo lugar, el comentario de la parte superior ofrece una cantidad limitada de explicación de por qué se caen de nuevo a descriptor de archivo 2. Mi conjetura es que stdin, stdout y stderr son más o menos conectado a '/ dev/tty /' de todos modos, a menos que se redirija. Y dado que las redirecciones más comunes para stdin y/o stdout (a través de tuberías o </>), pero con menos frecuencia para stderr, las probabilidades son que usar stderr sea más probable que todavía se conecte al "teclado".

+0

La razón para usar stderr es que stdin/stdout tienen más probabilidades de ser tuberías creadas por el shell de desove. Entrando o saliendo de menos es un noop, pero funciona. Pero redireccionar stderr de un comando menos específicamente tiene poco valor y no es probable que se haga. Así que apostar que stderr es "realmente" el dispositivo terminal es una suposición razonable. –

1

La misma pregunta con una respuesta en última instancia de la persona que lo solicitó está en linuxquestions aunque citan una fuente ligeramente diferente de less. Y no, no entiendo la mayor parte de ella, así que no puede dejar más allá de eso :)

-2

Parece ser Linux funcionalidad específica que envía a la entrada del teclado FD 2.

+1

descaradamente falso. Prueba esto en cualquier otro UNIX. – ephemient

Cuestiones relacionadas