Dos ventanas, mismo usuario, con mensajes de bash. En la ventana-1 escriba:
$ mkfifo f; exec <f
Entonces bash ahora está intentando leer desde el descriptor de archivo 0, que se asigna a la canalización con nombre f
. En la ventana-2, escriba:
$ echo ls > f
Ahora la ventana-1 imprime un ls y luego el caparazón muere. ¿Por qué?
Siguiente experimento: abra la ventana-1 nuevamente con exec <f
. En la ventana-2, escriba:
$ exec 3>f
$ echo ls >&3
Después de la primera línea anterior, la ventana 1 se activa e imprime un mensaje. ¿Por qué? Después de la segunda línea anterior, la ventana-1 imprime la ls
salida y el shell permanece vivo. ¿Por qué? De hecho, ahora en window-2, echo ls > f
no cierra el shell de window-1.
¡La respuesta debe tener que ver con la existencia del descriptor de archivo 3 de la ventana-2 que hace referencia a la tubería con nombre?
fuente
exec <f
,bash
no está tratando de leer a partirf
, primero se intenta abrir la misma. Elopen()
no regresará hasta que haya algún proceso de hacer otro abierto en el modo de escritura en el tubo (momento en el que el tubo se crea una instancia, y la cáscara leerá de entrada de ella).exec 3>f
se ejecuta, el primer shell emite un aviso. (Punto menor, ¿quiso decir "en modo de escritura " en su comentario?)Respuestas:
Tiene que ver con el cierre del descriptor de archivo.
En su primer ejemplo,
echo
escribe en su flujo de salida estándar que el shell abre para conectarlof
, y cuando termina, su descriptor se cierra (por el shell). En el extremo receptor, el shell, que lee la entrada de su flujo de entrada estándar (conectado af
) leels
, se ejecutals
y luego termina debido a la condición de fin de archivo en su entrada estándar.La condición de fin de archivo se produce porque todos los escritores de la canalización con nombre (solo uno en este ejemplo) han cerrado su final de la canalización.
En su segundo ejemplo,
exec 3>f
abre el descriptor de archivo 3 para escribirf
, luegoecho
escribels
en él. Es el shell que ahora tiene abierto el descriptor de archivo, no elecho
comando. El descriptor permanece abierto hasta que lo hagaexec 3>&-
. En el extremo receptor, el shell, que lee la entrada de su flujo de entrada estándar (conectado af
) leels
, se ejecutals
y luego espera más entrada (ya que el flujo aún está abierto).El flujo permanece abierto porque todos los escritores (el shell, la vía
exec 3>f
yecho
) no han cerrado su extremo de la tubería (exec 3>f
todavía está en vigor).He escrito sobre lo
echo
anterior como si fuera un comando externo. Lo más probable es que esté integrado en el caparazón. Sin embargo, el efecto es el mismo.fuente
No hay mucho: cuando no hay escritores en la tubería, parece cerrado para los lectores, es decir, devuelve EOF cuando se lee y se bloquea cuando se abre.
Desde la página de manual de Linux (
pipe(7)
pero vea tambiénfifo(7)
):Cerrar el final de la escritura es lo que sucede implícitamente al final de la
echo ls >f
, y como usted dice, en el otro caso, el descriptor de archivo se mantiene abierto.fuente
Después de leer las dos respuestas de @Kusalananda y @ikkachu, creo que entiendo. En la ventana 1, el shell está esperando que algo abra el extremo de escritura de la tubería y luego lo cierre. Una vez que se abre el final de la escritura, el shell en la ventana-1 imprime un mensaje. Una vez que se cierra el final de escritura, el shell obtiene EOF y muere.
Por el lado de la ventana-2 tenemos las dos situaciones descritas en mi pregunta: en la primera situación con
echo ls > f
, no hay descriptor de archivo 3, por lo que hemosecho
desove, y sustdin
ystdout
tener este aspecto:Luego
echo
termina y el shell cierra ambos descriptores. Dado que el descriptor de archivo 1 está cerrado y las referenciasf
, el final de escritura def
está cerrado y eso hace que un EOF a window-1.En la segunda situación, corremos
exec 3>f
en nuestro shell, haciendo que el shell tome este entorno:Ahora ejecutamos
echo ls >& 3
y el shell asigna descriptores de archivo de laecho
siguiente manera:Luego, el shell cierra los tres descriptores anteriores, incluidos
f
, perof
aún tiene una referencia desde el propio shell. Esta es la diferencia importante. Cerrar el descriptor 3 conexec 3>&-
cerraría la última referencia abierta y causaría un EOF a la ventana-1, como señaló @Kusalananda.fuente