2009-06-10 9 views
9

Aquí es un example para ilustrar lo que quiero decir:¿Por qué necesito cerrar fds cuando leo y escribo en la tubería?

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 

int main(void) 
{ 
     int  fd[2], nbytes; 
     pid_t childpid; 
     char string[] = "Hello, world!\n"; 
     char readbuffer[80]; 

     pipe(fd); 

     if((childpid = fork()) == -1) 
     { 
       perror("fork"); 
       exit(1); 
     } 

     if(childpid == 0) 
     { 
       /* Child process closes up input side of pipe */ 
       close(fd[0]); 

       /* Send "string" through the output side of pipe */ 
       write(fd[1], string, (strlen(string)+1)); 
      exit(0); 
    } 
    else 
    { 
      /* Parent process closes up output side of pipe */ 
      close(fd[1]); 

      /* Read in a string from the pipe */ 
      nbytes = read(fd[0], readbuffer, sizeof(readbuffer)); 
      printf("Received string: %s", readbuffer); 
    } 

    return(0); 

}

Sin embargo, ¿qué pasaría si uno de mis procesos tiene que escribir de forma continua a la tubería mientras que la otra tubería tiene que leer?

El ejemplo anterior parece funcionar solo para una escritura y una lectura.

+0

supongo que lo que La necesidad es un bloqueo. Luego, puede "bloquear el tubo" cuando un proceso lo utiliza. Cuando todos los procesos se realizan con el tubo uno de ellos lo cierra. – Skurmedel

+0

No se realizarán con tubería durante la duración del programa. –

+1

Ok. Luego, el último proceso de finalización lo cierra :) O abre toneladas de tuberías o sincroniza el acceso a una tubería. – Skurmedel

Respuesta

23

Su tubería es un flujo unidireccional, con un descriptor de archivo para cada extremo. No es necesario cerrar() cualquier extremo del tubo para permitir que los datos pasen a lo largo del mismo.

si su tubería abarca los procesos (es decir, se crea antes de una bifurcación() y luego el padre y el niño la usan para comunicarse) puede tener una escritura y un final de lectura. Entonces es una buena práctica cerrar los extremos no deseados de la tubería. Esto va a

  • asegúrese de que cuando el extremo de escritura cierra la tubería, se ve por el extremo de lectura. Como ejemplo, digamos que el niño es el lado de la escritura, y muere. Si el lado de escritura principal no se ha cerrado, el padre no obtendrá "eof" (lectura de longitud cero()) de la tubería, porque la tubería tiene un final de escritura abierto.
  • aclarar qué proceso está haciendo la escritura y qué proceso está haciendo la lectura en la tubería.

si su tubo se extiende por hilos (dentro del mismo proceso), entonces no cerrar los extremos no deseadas de la tubería. Esto se debe a que el proceso mantiene el descriptor de archivo y al cerrarlo para un subproceso se cerrará para todos los subprocesos y, por lo tanto, el conducto quedará inutilizable.

No hay nada que le impida tener un proceso escribiendo continuamente en la tubería y el otro proceso de lectura. Si este es un problema que tiene, entonces dénos más detalles para ayudarlo.

+0

Solo tengo un lector: principal y otro escritor: cadena secundaria: –

+4

Si se encuentra en un entorno enhebrado, los descriptores de archivos son compartidos por varios hilos. En estas circunstancias, NO cierre el extremo de lectura/escritura de la tubería hasta que haya terminado por completo; de lo contrario, la tubería se cerrará. Ahora entiendo la pregunta: cuando la tubería abarca los procesos, cierre los extremos no deseados, cuando la tubería abarque los hilos (dentro de un proceso), de modo que no cierre los extremos no deseados. – Beano

11

Después de realizar la horquilla, todos los fds están duplicados. Cada proceso tiene ambos extremos abiertos. Si solo quiere usar un extremo, debe cerrar el otro (si su proceso escribe, cierre el extremo de lectura).

Además del hecho obvio de que si no cierra los descriptores, el sistema operativo mantendrá entradas adicionales en la tabla de archivos abiertos, si no cierra el extremo de escritura de la tubería, el lector nunca recibirá EOF ya que todavía hay una forma de ingresar datos en la tubería. AFAIK (y IIRC) no hay ningún problema en no cerrar el fd de lectura en el otro proceso, es decir, además de abrir el archivo sin ningún motivo.

También se recomienda (como buena práctica, no es que afecte demasiado) que cierre todos los descriptores antes de salir de la aplicación (es decir, cierre el otro extremo después de completar la operación de lectura/escritura en cada proceso)

+0

Un poco de aclaración, yo no crear un proceso pero hilo, y paso escribir el final de la tubería al hilo para escribir –

+0

¿Por qué bifurca? entonces fork no crea hilos, crea procesos hijo. – qrdl

+0

Eso fue solo un ejemplo. De hecho, comencé un hilo separado de los procesos. –

0

Una tubería no le dará un canal bidireccional, tampoco será multidifusión. Una tubería como solo dos extremos, no tiene un final de escritura y un final de lectura múltiple.

Si quiere muchos lectores, necesita tantos tubos como tenga un proceso de lectura.

+0

Solo tengo un lector - padre y un escritor - hijo –

0

"El ejemplo anterior parece funcionar solo para una escritura y una lectura."

Esto se debe a que después de leer y escribir su código sale. Debe seguir escribiendo en un bucle y leer en un bucle para lograr la continuidad. No parece tener nada que ver con el cierre del FD. en una respuesta anterior que necesita un extremo en cada proceso, de modo que el otro es cerrado.

espero que entiendo el derecho de consulta.

0

sólo para la sincronización, para garantizar la atomicidad de la operación

Cuestiones relacionadas