2017-03-03 1 views
1

Nous devons écrire un programme C qui redirigera essentiellement stdin d'une commande/programme vers une autre commande/programme stdout, en utilisant des tuyaux. Si le programme sur la ligne de commande a été passé ./a.out ls -l \; more, il doit rediriger la stdout de ls -l à more, avec le \; étant le délimiteur. Ce programme devrait fonctionner pour n'importe quelle commande/programme qui est dans notre chemin: ./a.out cat filename.c \; more, devrait être le même que de taper: cat filename.c | more.Piping pour rediriger stdout d'un programme vers stdin d'un autre

Mon problème est que mon programme ne semble pas fonctionner correctement ou que les tuyaux ne fonctionnent pas comme prévu. Fondamentalement, je ne reçois aucune sortie en dehors du débogage de l'instruction d'impression que j'ai placé. Pour être précis, le programme imprime: Exec ... puis ERROR, qui est tout dans le code parent.

#include <fcntl.h> 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <unistd.h> 
    #include <sys/types.h> 
    #include <sys/wait.h> 
    void pipeit(char * pro1, char * pro2, char * p1args[], char * p2args[]) 
    { 
    pid_t pid; 
    int fd[2]; 
    int st; 
    pipe(fd); 
    pid = fork(); 

    if(pid < 0) 
    { 
     printf("Error Forking...\n"); 
     exit(-1); 
    } 
    else if(pid == 0) 
    { 
     dup2(fd[1],1); 
     close(fd[0]); 
     close(1); 
     printf("Exec 1...\n"); 
     execv(pro1, p1args); 
     printf("ERROR\n"); 
    } 
    else 
    { 
     waitpid(pid,&st,0); 
     if(st<0) 
     { 
      printf("Child Error\n"); 
     } 
     dup2(fd[0],0); 
     close(fd[1]); 
     close(0); 
     printf("Exec...\n"); 
     execv(pro2,p2args); 
     printf("ERROR\n"); 
    } 
    return; 
    } 
    /* THIS IS JUST COMMAND LINE PARSING */ 
    int main(int argc, char * argv[]) 
    { 
    int i = 1; 
    char * pro1; 
    char * pro2; 
    char * first[argc+1]; 
    char * second[argc+1]; 
    while(i<argc && argv[i][0] != ';') 
    { 
     if(i == 1) 
     { 
      pro1 = argv[i]; 
     } 
     else 
     { 
      first[i] = argv[i]; 
     } 
     i++; 
    } 
    first[i] = NULL; 
    while(i<argc) 
    { 
     if(argv[i][0] == ';') 
     { 
      i++; 
      pro2 = argv[i]; 
     } 
     else 
     { 
      second[i] = argv[i]; 
     } 
     i++; 
    } 
    second[i] = NULL; 
    pipeit(pro1,pro2,first, second); 
    return 0; 
    } 

Répondre

0

Chez l'enfant, vous avez:

dup2(fd[1],1); 
    close(fd[0]); 
    close(1); 

Duplicata le tuyau de sortie standard, mais ferme, la sortie standard. Corrige en ne fermant pas la sortie standard, et en fermant les deux extrémités du tuyau. Règle de base: si vous dupliquez une extrémité d'un tube en entrée, sortie ou erreur standard, vous devez fermer les deux descripteurs de canal d'origine.

dup2(fd[1],1); 
    close(fd[0]); 
    close(fd[1]); 

Vous avez le problème analogue dans le parent avec l'entrée standard étant fermée.

Vous avez également le wait() au mauvais endroit. Les processus doivent s'exécuter simultanément. Si le premier processus dans le pipeline génère tellement de données que le tuyau ne peut pas tout contenir, le processus va bloquer. Si l'autre processus attend la fin du premier processus avant de lire quoi que ce soit, cela ne fonctionnera pas bien.