unistd - ¿Por qué deberías cerrar una tubería en linux?
pipes tutorial c (2)
Cuando se usa una tubería para la comunicación de proceso-proceso, ¿cuál es el propósito de cerrar un extremo de la tubería?
Por ejemplo: ¿Cómo enviar una cadena simple entre dos programas usando tuberías?
Observe que un lado de la tubería está cerrado en los procesos hijo y padre. ¿Por qué se requiere esto?
El número de descriptores de archivo que se pueden abrir en un momento dado es limitado. Si sigues abriendo tuberías y no las cierras muy pronto, te quedarás sin FD y ya no podrás abrir nada: ni tuberías, ni archivos, ni enchufes, ...
Otra razón por la que puede ser importante cerrar la tubería es cuando el cierre en sí tiene un significado para la aplicación. Por ejemplo, un uso común de tuberías es enviar el errno
desde un proceso secundario al padre cuando se usa fork
y exec
para iniciar un programa externo :
- El padre crea la canalización, llama a la
fork
para crear un proceso secundario, cierra su extremo de escritura e intenta leer desde la tubería. - El proceso hijo intenta usar
exec
para ejecutar un programa diferente:- Si
exec
falla, por ejemplo, porque el programa no existe, el niño escribeerrno
en la canalización, el padre lo lee y sabe qué fue lo que salió mal y puede avisarle al usuario. - Si
exec
tiene éxito, la tubería se cierra sin que se escriba nada. La función deread
en el padre devuelve 0 que indica que la tubería se cerró y sabe que el programa se inició con éxito.
- Si
Si el padre no cerró su extremo de escritura de la tubería antes de intentar leer desde la tubería, esto no funcionaría porque la función de read
nunca regresaría cuando exec
sea exitoso.
Si conecta dos procesos, principal y secundario, mediante una tubería, cree la tubería antes de la bifurcación.
La horquilla hace que ambos procesos tengan acceso a ambos extremos de la tubería. Esto no es deseable.
Se supone que el lado de lectura debe saber que el escritor ha terminado si nota una condición de EOF. Esto solo puede suceder si todos los lados de escritura están cerrados. Así que es mejor si cierra su escritura FD lo antes posible.
El escritor debe cerrar su FD de lectura solo para no tener demasiadas FD abiertas y, por lo tanto, alcanzar un límite tal vez existente de FD abiertas. Además, si el único lector muere, el escritor recibe una notificación al respecto al obtener un SIGPIPE o al menos un error de EPIPE (según cómo se definan las señales). Si hay varios lectores, el escritor no puede detectar que "el verdadero" desapareció, continúa escribiendo y se atasca mientras la escritura FD se bloquea en la esperanza, el lector "no utilizado" leerá algo.
Así que aquí en detalle lo que sucede:
- el proceso principal llama a
pipe()
y obtiene 2 descriptores de archivo: llamémoslord
ywr
. - proceso padre llama a
fork()
. Ahora ambos procesos tienen unrd
y unwr
. Supongamos que se supone que el proceso hijo es el lector.
Entonces
- el padre debe cerrar su extremo de lectura (para no perder FD y para la detección adecuada del lector moribundo) y
- el niño debe cerrar su extremo de escritura (para que sea posible detectar la condición EOF).