Recién comencé a aprender cómo Everything Is A File TM en Linux, lo que me hizo preguntarme qué pasaría si literalmente leía de / dev / stdout:
$ cat /dev/stdout
^C
$ tail /dev/stdout
^C
(El ^C
soy yo matando el programa después de que se cuelga).
Cuando lo intento vim
, aparece el mensaje impensable: "/ dev / stdout" no es un archivo. ¡Jadear!
Entonces, ¿qué ocurre? ¿Por qué recibo mensajes de error o bloqueos cuando intento leer estos "archivos"?
Respuestas:
No está recibiendo "bloqueos" de
cat(1)
ytail(1)
, solo están bloqueando la lectura.cat(1)
espera la entrada y la imprime tan pronto como ve una línea completa:Aquí escribí
foo
Enterbar
EnterCTRL- D.tail(1)
espera la entrada y la imprime solo cuando puede detectarEOF
:Aquí escribí de nuevo
foo
Enterbar
EnterCTRL- D.Vim es el único que te da un error. Lo hace porque se ejecuta en
stat(2)
contra/dev/stdout
y descubre que no tiene elS_IFREG
bit establecido./dev/stdout
es un archivo, pero no un archivo normal . De hecho, hay algo de baile en el núcleo para darle una entrada en el sistema de archivos. En Linux:En OpenBSD:
En FreeBSD:
fuente
(Casi) todo es un archivo, pero no todo es un archivo normal . No tiene sentido llamar a un editor de texto en algo que es un archivo especial como un directorio, un socket de red, un puerto serie, etc.
El archivo
/dev/stdout
puede ser una de varias cosas dependiendo de la variante de Unix:En cualquier caso, abrir
/dev/stdout
archivos similares crea un nuevo descriptor de archivo que está asociado con el mismo archivo que la aplicación ya tiene abierto en el descriptor de archivo 1. “Salida estándar” significa el descriptor de archivo 1, y es solo una convención que se utilice este descriptor de archivo para salida: al núcleo no le importa.Cuando ejecuta un programa en un terminal, los tres descriptores estándar (0 = entrada estándar, 1 = salida estándar, 2 = error estándar) se abren en el dispositivo terminal. La lectura desde ese dispositivo devuelve caracteres escritos por el usuario, y la escritura en ese dispositivo muestra texto en la ventana del terminal. (No existe una forma estándar, dado un dispositivo terminal, de leer la salida que muestra o inyectarle entradas).
Cuando ejecuta
cat /dev/stdout
, eso hace exactamente lo mismo quecat /dev/stdin
ocat /dev/stderr
, porque estos tres descriptores de archivo están conectados al mismo archivo: le dicecat
que lea desde el terminal. Eso es lo quecat
sin argumento hace también.Si ejecutó
cat /dev/stdout >foo
,/dev/stdout
se referiría al archivofoo
, ese comando es equivalente acat foo >foo
. Dependiendo de lacat
implementación, podría producirse un error (la versión de GNU se queja de que "el archivo de entrada es el archivo de salida"), o podría no hacer nada porque lee del archivofoo
que está vacío (>foo
solo lo truncó). Con una versión decat
que no detecta este caso especial, sifoo
no está vacío, entoncescat /dev/stdout >>foo
o el equivalentecat foo >>foo
agregaría el contenido del archivo a sí mismo indefinidamente.Cuando ejecuta
vim /dev/stdout
, se queja porque no sabe cómo editar un terminal (eso simplemente no tiene sentido).fuente
cat
ytail
está buscando contenido opcional seguido de un final de archivo./dev/stdout
sigue abierta, por lo quecat
, ytail
sólo seguir buscando.fuente