Ayuda - Llamadas al sistema UNIX 2.0.

P

Hola gente,

En recomendacion de ElkaoD, abro otro hilo para otra duda acerca de las llamadas al sistema.

Necesito hacer un programa que mediante la llamada, ./program fsalida <fentrada.

1.- Haga un rev de fentrada y este resultado lo muestre por stdout
2.- Al resultado de ese rev se le haga un wc y lo muestre en el fsalida

El problema que tengo es que si pongo que muestre el resultado del rev por stdout, el resultado del wc, no es correcto, me da 0, sin embargo, si no pongo el resultado del rev, en el fsalida si que me da el resultado correcto.

Dejo aquí el código. Gracias

#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

#define N 1024

int main(int argc, char * argv[]){

int fdin,fdout; //ficheros de entrada y salida
int nr,nr1,pid;
int p1[2];      //pipe1
int p2[2];               //pipe2
char buffer[N];
char buffer1[N];

if (argc!=2){                                                                                                           // Control de argumentos
        perror("Número de argumentos incorrecto\n");
        exit(EXIT_FAILURE);
}

pipe(p1); //Creamos el pipe1
pipe(p2); //Creamos el pipe2


//HIJO 1
pid=fork();
if (pid<0){                                                                                             //Control de errores
        perror("Error al crear el pid\n");
        exit(EXIT_FAILURE);
}
if (pid==0){
        close(p1[0]);
        dup2(p1[1],1);
        close(p1[1]);
        close(p2[0]);
        close(p2[1]);
        execlp("rev","rev",NULL);
                perror("Error al ejecutar el comando rev\n");
                exit(EXIT_FAILURE);
}
//HIJO 2

pid=fork();
if (pid<0){                                                                                             //Control de errores
        perror("Error al crear el pid\n");
        exit(EXIT_FAILURE);
}
if (pid==0){
        close(p1[1]);
        dup2(p1[0],0);
        close(p1[0]);
        close(p2[0]);
        dup2(p2[1],1);
        close(p2[1]);
        execlp("wc","wc","-w",NULL);
                perror("Error al ejecutar el comando wc\n");                    //Control de errores
                exit(EXIT_FAILURE);
}
close(p1[1]);
close(p2[1]);



fdout=creat(argv[1],S_IRWXU);           //Creamos el fichero de salida y vamos leyendo de la segunda tubería para escribirlo en el fichero
for(;;){
        nr=read(p1[0],buffer,N);
                if (nr<=0){
                        break;
                }
        write(1,buffer,nr);
}
for(;;){
        nr=read(p2[0],buffer,N);
                if(nr<=0){
                        break;
                }
        write(fdout,buffer,nr);
}
close(p1[0]);
close(p2[0]);
close(fdout);
wait(NULL);
wait(NULL);
return 0;
}
elkaoD

Si no entiendo mal, ¿tu problema es que al escribir por stdout, stdin se consume y el otro proceso ya no recibe nada?

¿Qué tengo que tocar para que el rev si salga por stdout? (ahora solo me muestra el wc correcto en lugar de guardarlo en el archivo).

¿Cuál es el esquema de pipes?

EDIT: no funcionaba porque en el primer for de salida pones p2 y debería ser p1. Ya veo lo que dices de que el wc da 0.

A mi entender, desde el proceso hijo (rev) tienes que escribir en dos pipes diferentes porque dos procesos no pueden consumir de la misma pipe. Así es como lo hace tee.

La idea sería que el proceso de rev lee de stdin y escribe a dos pipes: uno consumido por el wc y otro consumido por el proceso padre al imprimir.

1 respuesta
P

#2

No entiendo exactamente a que te refieres... En el rev habría que escribir lo que se escribe en p1 también en p2?

1 respuesta
elkaoD

#3 el esquema sería:

            /-p1-> wc -p3-> fout
-stdin-> rev
            \-p2-> stdout

En resumen: el proceso de rev escribe en DOS pipes, uno que consume wc y otro que consume el padre e imprime en stdout.

De todas formas, ¿tienes que escribir a fout desde el padre o puedes hacerlo desde el hijo directamente? Te ahorras un pipe.

            /-p1-> wc -> fout
-stdin-> rev
            \-p2-> stdout

1 respuesta
P

#4

Puedo hacerlo desde el hijo, de hecho, el ejercicio pone que únicamente se pueden utilizar dos pipes y dos hijos

Usuarios habituales