2009-06-10 4 views
9

Ecco un example per illustrare quello che voglio dire:Perché devo chiudere FDS durante la lettura e la scrittura sulla pipe?

#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); 

}

Tuttavia, cosa succede se uno dei miei processi ha bisogno di scrivere in modo continuo al tubo, mentre l'altro tubo ha bisogno di leggere?

L'esempio precedente sembra funzionare solo per una scrittura e una lettura.

+0

Credo che quello che si è necessario un lock, quindi è possibile "bloccare il pipe" quando un processo lo utilizza. Quando tutti i processi vengono eseguiti con il pipe uno di thme lo chiude. – Skurmedel

+0

Non saranno fatti con pipe per tutta la durata del programma. –

+1

Ok. Quindi l'ultimo processo di finitura lo chiude :) O si aprono tonnellate di pipe o si sincronizza l'accesso a una pipe. – Skurmedel

risposta

23

La tua pipe è un flusso unidirezionale - con un descrittore di file per ciascuna estremità. Non è necessario chiudere() entrambe le estremità del tubo per consentire il passaggio dei dati lungo di esso.

se i vostri tubi campate processi (ovvero viene creato prima di un fork() e poi il genitore e il bambino lo usano per comunicare) si può avere uno di scrittura e lettura e una delle estremità. Quindi è buona norma chiudere le estremità indesiderate del tubo. Questo sarà

  • assicurarsi che quando la fine della scrittura chiude il tubo è visto dalla fine di lettura. Ad esempio, diciamo che il bambino è il lato di scrittura, e muore. Se il lato di scrittura genitore non è stato chiuso, il genitore non otterrà "eof" (zero length read()) dalla pipe - perché la pipe ha una scrittura write-end.
  • chiarire quale processo sta eseguendo la scrittura e quale processo sta eseguendo la lettura sulla pipe.

se il tubo si estende fili (all'interno dello stesso processo), quindi non chiudere le estremità del tubo indesiderate. Questo perché il descrittore di file è trattenuto dal processo, e chiudendolo per un thread lo chiuderà per tutti i thread, e quindi la pipe diventerà inutilizzabile.

Non c'è nulla che impedisca di scrivere continuamente un processo alla pipe e l'altro processo di lettura. Se questo è un problema, ci stai dando maggiori dettagli per aiutarti.

+0

Ho solo un lettore - padre e uno scrittore - thread figlio - –

+4

Se ci si trova in un ambiente con thread, i descrittori di file vengono condivisi dai vari thread. Quindi in queste circostanze NON chiudere l'estremità di lettura/scrittura del tubo finché non si è completamente finito, altrimenti il ​​tubo si chiuderà. Ora capisco la domanda - quando la pipa si estende su processi, chiude le estremità indesiderate, quando la pipa si estende su fili (all'interno di un processo), quindi non chiudere le estremità indesiderate. – Beano

11

Dopo l'esecuzione della forcella, tutti i file vengono duplicati. Ogni processo ha entrambe le estremità del tubo aperto. Se si desidera utilizzare solo un'estremità, è necessario chiudere l'altra (se il processo è in scrittura, chiudere la parte di lettura).

Oltre al fatto ovvio che se non si chiudono i descrittori il sistema operativo manterrà le voci aggiuntive nella tabella dei file aperti, se non si chiude la fine della scrittura della pipe, il lettore non riceverà mai EOF poiché c'è ancora un modo per inserire dati nella pipe. AFAIK (e IIRC) non ci sono problemi nel non chiudere la lettura di fd nell'altro processo - ovvero, a parte il fatto che il file sia aperto senza motivo.

Si consiglia inoltre (come buona norma, non che questo influenzi troppo) di chiudere tutti i descrittori prima di uscire dall'applicazione (ovvero, chiudere l'altra estremità del tubo dopo che l'operazione di lettura/scrittura è stata completata in ogni processo)

+0

Un piccolo chiarimento, io non creare un processo, ma thread, e io passo scrivere fine del tubo al thread da utilizzare per scrivere –

+0

Perché si forchetta quindi? fork non crea thread, crea processi figli. – qrdl

+0

Questo era solo un esempio. un thread separato dai processi –

0

Una pipe non ti darà un canale bidirezionale, né sarà multicasting. Una pipe come solo due estremità, non ha una fine di scrittura e più letture.

Se si desidera avere molti lettori, è necessario un numero di pipe sufficiente per il processo di lettura.

+0

Ho solo un lettore - padre e uno scrittore - thread figlio –

0

"L'esempio precedente sembra funzionare solo per una scrittura e una lettura."

Questo perché dopo aver letto e scritto il codice, è necessario uscire, è necessario continuare a scrivere in un ciclo e leggere in loop per ottenere continuità, non sembra avere nulla a che fare con la chiusura FD. in una risposta precedente è necessario un estremo su ogni processo in modo l'altra è chiusa.

Spero capisco il diritto di query.

0

solo per la sincronizzazione, per garantire l'atomicità di funzionamento