2009-11-07 12 views
9

Estoy intentando crear un shell simple en C para Unix. He podido hacer todo el análisis de comandos y ejecución, pero tengo un problema con la tubería. Creo que el problema es que no me conecto a la tubería correcta para la entrada del segundo comando.Problema con los comandos de canalización en C

Por ejemplo, si escribo "ls | wc", se pausará después del comando "wc", que creo que es porque está esperando la entrada. Creo que el problema es cuando uso dup2 (lectura [i], 0), y no se engancha en la tubería correcta.

Sé que esta es una pregunta un poco amplia, pero si hay algún indicador que pueda obtener, lo agradecería. Aquí está el código que crea nuevos procesos y trata de canalizarlos.

int fileds[2]; 
    int reading[num_cmds]; 
    int writing[num_cmds]; 

    int p; 
    for(p=0; p < num_cmds; p++) 
    { 
     reading[p] = -1; 
     writing[p] = -1; 
    } 

    int j; 
    for(j=0; j < num_cmds-1; j++) //Create pipes for commands 
    { 
     int fileds[2]; 
     pipe(fileds); 
     reading[j+1] = fileds[0]; 
     writing[j] = fileds[1]; 
    } 

    int i = 0; 
    for(i = 0; i < num_cmds;i++) 
    {   
     cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg); //Get command and args 

     pid_t childpid; 
     int status; 
     childpid=fork(); 

     if (childpid >= 0) 
     { 
      if (childpid == 0) 
      {    
       if(writing[i] != -1) 
       { 
        dup2(writing[i],1); 
        close(writing[i]); 
       } 

       if(reading[i] != -1) 
       { 
        dup2(reading[i],0); 
        close(reading[i]); 
       } 

       int h; 
       for(h = 0; h < num_cmds; h++) 
       { 
        close(writing[h]); 
        close(reading[h]); 
       } 

       if(execvp(cmd_args[0],cmd_args) == -1) 
       { 
        perror("Problem with command"); 
        exit(0); 
       } 
      } 
      else 
      { 
       wait(&status); 
       int m; 
       for(m = 0; m < num_cmds; m++) 
       { 
        if(writing[m] != -1) close(writing[m]); 
        if(reading[m] != -1) close(reading[m]); 
       } 
      } 
     } 
     else 
     { 
      perror("fork"); 
      continue; 
     } 


     input_file[0] = 0; 
     output_file[0] = 0; 
     run_bg = 0; 
    } 

} 



ACTUALIZACIÓN: yo era capaz de entenderlo, gracias a Richard. Fue una combinación de cerrar los descriptores de archivo en el orden incorrecto y no cerrar ninguno. Aquí está el código de trabajo.

int fileds[2]; 
    int reading[num_cmds]; 
    int writing[num_cmds]; 

    int p; 
    for(p=0; p < num_cmds; p++) 
    { 
     reading[p] = -1; 
     writing[p] = -1; 
    } 

    int j; 
    for(j=0; j < num_cmds-1; j++) 
    { 
     int fileds[2]; 
     pipe(fileds); 
     reading[j+1] = fileds[0]; 
     writing[j] = fileds[1]; 
    } 

    int i = 0; 
    for(i = 0; i < num_cmds;i++) 
    {   
     cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg); 

     pid_t childpid; 
     int status; 
     childpid=fork(); 

     if (childpid >= 0) 
     { 
      if (childpid == 0) 
      {    
       if(writing[i] != -1) 
       { 
        close(1); 
        dup2(writing[i],1); 
       } 

       if(reading[i] != -1) 
       { 
        close(0); 
        dup2(reading[i],0); 
       } 

       if(execvp(cmd_args[0],cmd_args) == -1) 
       { 
        perror("Problem with command"); 
        exit(0); 
       } 
      } 
      else 
      { 

       wait(&status); 
       close(writing[i]); 

       if(i > 0) 
       { 
        close(reading[i]); 
       } 
      } 
     } 
     else 
     { 
      perror("fork"); 
     } 


     input_file[0] = 0; 
     output_file[0] = 0; 
     run_bg = 0; 
    } 

Respuesta

2

Creo que su problema puede ser que espere cada proceso dentro del ciclo y luego cierre todos los descriptores de archivo. Esto hace que los descriptores de archivos no sean válidos para la próxima llamada a dup2() y da como resultado stdin para el siguiente proceso sin cambios.

Solo supongo que no he ejecutado el código.

+0

Creo que tienes razón. Intenté comentar el if (reading [m]! = -1) close (reading [m]); en el bucle, y eso me permite canalizar 2 comandos. ¡Gracias por señalarme en la dirección correcta! – mbxtr

0

Cuando escribo "ls | wc" wc hace como se esperaba e imprime el número de palabras de salida por el comando ls. Recuerde que cuando está conectando comandos con "|" no es necesario que cree tuberías en su aplicación. El primer comando necesita dar salida a stdout y el segundo comando necesita leer ese resultado desde estándar.

+0

Este es un proyecto para entender cómo funciona la tubería, por lo que debo ser capaz de configurar la tubería. "ls | wc" funciona en una terminal normal, pero necesito emular eso en este programa. Por lo que entiendo, necesito establecer la salida del primer comando - "ls" en este caso para ser la salida de la tubería, y la entrada del segundo comando, para ser la entrada de la tubería. – mbxtr

+0

Bueno, si está implementando un caparazón para proporcionar este mecanismo de tubería, entonces necesita usar tuberías o algún mecanismo similar. Creo que el que pregunta sabe estos problemas; él pregunta por qué no está funcionando. – BobbyShaftoe

Cuestiones relacionadas