2010-04-26 17 views
5

OK J'ai un programme qui crée deux tuyaux -> forks -> stdin et stdout de l'enfant sont redirigés à une extrémité de chaque tuyau -> le parent est connecté à l'autre extrémité des tuyaux et essaie de lire le flux associé à sortie de l'enfant et l'imprimer à l'écran (et je vais aussi le faire écrire à l'entrée de l'enfant par la suite). Le problème est que, lorsque le parent tente d'identifier le flux de sortie de l'enfant, il s'arrête et attend jusqu'à ce que l'enfant meure, puis imprime la sortie. Si l'enfant ne sort pas, il attend toujours pour toujours. Que se passe-t-il? Je pensais que peut-être que les fgets bloqueraient jusqu'à ce que QUELQUE CHOSE soit dans le flux, mais ne bloquent pas tout le jeu jusqu'à ce que l'enfant abandonne ses descripteurs de fichiers.ne peut pas lire du flux jusqu'à la sortie de l'enfant?

Voici le code:

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

Répondre

5

L'enfant devrait probablement fflush() sa sortie, et/ou mettre fin à des lignes correctement. Sinon, la mise en mémoire tampon d'E/S peut s'accrocher aux données pendant un certain temps.

Vous pouvez essayer de définir l'indicateur O_NONBLOCK (en utilisant fcntl()) sur le descripteur de fichier de sortie de l'enfant avant de passer le contrôle, mais cela vous obligera à modifier votre code parent en conséquence. Comme indiqué dans les commentaires, cela ne vous aidera pas à surmonter la mise en mémoire tampon effectuée au niveau de la bibliothèque standard C si l'enfant utilise des E/S basées sur FILE.

+0

Hmmm, vous avez raison. Quand je fflush la sortie, cela fonctionne. Le problème est, je n'ai aucun moyen de contrôler l'enfant. Je peux seulement le contrôler avec mon programme de test car je peux éditer le code source ... Comment est-ce que je m'assure que n'importe quel programme qui est execvp'ed a sa sortie rincée ou non tamponnée ou quelque chose ... arghhh – BobTurbo

+0

Attendez, voici le code de l'enfant du test: printf ("Entrer l'entrée: \ n"); fflush (stdout); si j'enlève le/n ou le fflush, ça retarde .. j'en ai besoin pour le lire sans avoir un/n et .. sans que j'éclate. – BobTurbo

+0

Je ne devrais probablement pas utiliser fgets ... mais je ne suis pas sûr que cela résout le bit fflushing. – BobTurbo