2010-04-26 12 views
5

OK Ho un programma che crea due pipe -> fork -> lo stdin e lo stdout del bambino vengono reindirizzati a un'estremità di ogni pipe -> il genitore è connesso agli altri capi delle pipe e prova a leggere lo stream associato a l'output del bambino e stamparlo sullo schermo (e lo farò anche scrivere all'input del bambino alla fine).non è in grado di leggere dallo stream fino all'uscita del figlio?

Il problema è che quando il genitore tenta di gestire il flusso di output del figlio, si blocca e attende fino a quando il figlio non muore su fgets e quindi stampa l'output. Se il bambino non esce, aspetta solo per sempre. Cosa sta succedendo? Ho pensato che forse fgets avrebbe bloccato fino a quando SOMETHING era nello stream, ma non lo avrebbe bloccato fino a quando il figlio non ha rinunciato ai suoi descrittori di file.

Ecco il codice:

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

int main(int argc, char *argv[]) { 
FILE* fpin; 
FILE* fpout; 
int input_fd[2]; 
int output_fd[2]; 
pid_t pid; 
int status; 
char input[100]; 
char output[100]; 
char *args[] = {"/somepath/someprogram", NULL}; 
fgets(input, 100, stdin); // the user inputs the program name to exec 

pipe(input_fd); 
pipe(output_fd); 
pid = fork(); 

if (pid == 0) { 
    close(input_fd[1]); 
    close(output_fd[0]); 
    dup2(input_fd[0], 0); 
    dup2(output_fd[1], 1); 
    input[strlen(input)-1] = '\0'; 
    execvp(input, args); 
} 
else { 
    close(input_fd[0]); 
    close(output_fd[1]); 
    fpin = fdopen(input_fd[1], "w"); 
    fpout = fdopen(output_fd[0], "r"); 
    while(!feof(fpout)) { 
    fgets(output, 100, fpout); 
    printf("output: %s\n", output); 
    } 
} 

return 0; 
} 

risposta

5

Il bambino dovrebbe probabilmente fflush() sua uscita, e/o terminare le linee correttamente. In caso contrario, il buffering I/O può rimanere sospeso per un certo periodo di tempo.

È possibile provare a impostare il flag O_NONBLOCK (utilizzando fcntl()) sul descrittore del file di output del figlio prima di passare il controllo, ma ciò richiederà la modifica del codice padre di conseguenza. Come indicato nei commenti, tuttavia, questo non aiuterà a superare il buffering eseguito a livello di libreria standard C se il bambino utilizza l'I/O basato su FILE.

+0

Hmmm, hai ragione. Quando spengo l'uscita, funziona. Il problema è che non ho modo di controllare il bambino. Posso solo controllarlo con il mio programma di test in quanto posso modificare il codice sorgente ... Come faccio a essere sicuro che qualsiasi programma che è execvp'ed ha il suo output arrossato o non-buffered o qualcosa ... arghhh – BobTurbo

+0

Aspetta, ecco il codice del test del bambino: printf ("Immetti input: \ n"); fflush (stdout); se prendo il/n o il fflush, ritarda .. Ho bisogno di leggerlo senza avere un/n e .. senza che io stia fflushing. – BobTurbo

+0

Probabilmente non dovrei usare fgets ... ma non sono sicuro che risolva il problema del fflushing. – BobTurbo

Problemi correlati