Duda con C++ y procesos en linux.

Iniciado por SARGE553413, 24 Enero 2014, 22:08 PM

0 Miembros y 1 Visitante están viendo este tema.

SARGE553413

Hola a todos.

Tengo que hacer un programa en c++ que ejecute cualquier nº de mandatos de la shell encadenados por tuberías. He conseguido hacerlo para una sola tubería, y para 2, pero cuando paso al caso general ('n' tuberías no consigo que funcione).

Os adjunto el código:


/**
   Ejecuta los mandatos de la lista 'args' encadenados por tuberías.
   'fd' vector de descriptores
       inicial (se crea en el main y se le pasa a este metodo)
   'i' número de iteraciones que llevo hechas. Con cada nuevo proceso
       creado, se incrementa en 1.
   'max' número de mandatos en el vector de argumentos ('args')
**/
int p1(char *args[],int fd[],int &i,const int &max){
   //Voy a ejecutar un mandato, incremento i.
   i++;
   //Creo la tubería para el siguiente proceso.
   pipe(fd);
   //Creo el proceso
   int pid=fork();
   switch(pid){
       case -1:
           //si hay error....
           exit(-1);
       case 0:
           //Soy el proceso hijo, lo que hago es:
           //Creo otro vector de descriptores (para la tubería
           //que mi hijo tendrá que heredar.
           int fd2[2];
           //Redirecciono mi salida estándar para que mi
           //padre pueda leer la salida del mandato que voy
           //a ejecutar
           outRedir(fd);
           //Si no soy el proceso que va a ejecutar el último mandato:
           if(i<max){
               //Repito lo anterior para crear mi tubería, mi proceso hijo etc.
               p1(args,fd2,i,max);
           //Si soy el proceso que va a ejecutar el último mandato:
           }else{
               //Ejecuto y salgo
               execlp(args[max-1],args[max-1],NULL);
               exit(0);
           }
           break;
       default:
           //Soy el proceso padre (pero era el hijo en la anterior llamada
           //recursiva)
           //Redirijo entrada
           inRedir(fd2);
           //ejecuto
           execlp(args[i-1],args[i-1],NULL);
           exit(0);
   }
}

/**
   Dado un vector de descriptores:
       -Cierra el extremo de escritura
       -Redirige stdin al extremo de lectura de la tuberia
       -Stdin ya redireccionado, cierra el extremo de lectura
**/
void inRedir(int fd[]){
   close(fd[1]);
   dup2(fd[0],0);
   close(fd[0]);
}

/**
   Dado un vector de descriptores:
       -Cierra el extremo de lectura
       -Redirige extremo de escritura a stdout
       -Stout ya redireccionado, cierra el extremo de escritura
**/
void outRedir(int fd[]){
   close(fd[0]);
   dup2(fd[1],1);
   close(fd[1]);
}


Muchas gracias.

SARGE553413

Hola de nuevo, he seguido intentándolo y creo que un problema era que en el fragmento de código del "default" uso 'fd2' cuando debería usar 'fd', esto es:


default:
            //Soy el proceso padre (pero era el hijo en la anterior llamada
            //recursiva)
            //Redirijo entrada
            inRedir(fd) //antes ponia esto ==== > inRedir(fd2);
            //ejecuto
            execlp(args[i-1],args[i-1],NULL);
            exit(0);


Estoy ejecutando pasandole como mandatos ls, cat y wc para que haga: "ls | cat | wc". El error que me da es:
"wc: entrada estándar: Error de entrada/salida"

SARGE553413

#2
He segudido probando.

He cambiado el orden de los parámetros, en lugar de poner ls,cat y wc ahora pongo:
wc,cat y ls.

¿Me puede explicar alguien por qué pasa esto? No entiendo nada..


EDITO: lo he solucionado cambiando el execlp([i-1],[i-1],NULL) por
execlp([max-i],[max-i],NULL).

Sigo sin entender por qué pasa esto.
Ahora necesito ayuda para pasarlo de recursivo a iterativo, ¿alguien me puede ayudar? Gracias