22 nov 2013

Los Pipes! (C Boys)

Hoy volvemos rememorando ejercicios pasados, hoy hablamos de pipes, esas graciosas tuberías que servían para comunicar información entre procesos. Esas tubería unidireccionales, con las que un proceso leía y en las que otro escribía. Aquellas tuberías en las que nos perdíamos, se nos rompían y en ocasiones nos llegaban bytes de más. Porque aún me acuerdo de ellas, porque aún sé lo que son y porque al final consiguieron que en distintos exámenes me sintiera orgulloso, por eso hoy os traemos los pipes.
Problema: 
Realice un programa en C denominado ping-pong. Dicho programa consistirá en dos procesos hijos. El proceso hijo1 enviará la cadena "ping" a lo que el proceso hijo2 responderá con la cadena "pong". La ejecución se limitará a diez iteraciones, tras lo cual ambos procesos terminarán su ejecución.
Nuestra solución:
En primer lugar se inicializarán las tuberías (se necesitan dos, ya que como son unidireccionales, la primera servirá para que el proceso 1 mande PING al proceso 2, mientras que la segunda servirá para que el proceso 2 mande PONG al proceso 1) crearán los dos procesos hijos mediante la instrucción fork(). Los procesos hijos llamarán a su función correspondiente, mientras que el padre no hace nada y se queda a la espera de que los procesos hijos finalicen.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
char *ping = “PING”;
char *pong = “PONG”;
int
main(int argc, char *argv[]){
int tuberia1[2], tuberia2[2];
int i;
int hijo;
if(pipe(tuberia1)== -1){
perror(“error”);
exit(EXIT_FAILURE);
}
if(pipe(tuberia2)== -1){
perror(“error”);
exit(EXIT_FAILURE);
}
for(i=0;i<2;i++){
hijo = fork();
if(hijo == -1){
perror(“error”);
exit(EXIT_FAILURE);
}
if(hijo == 0){
if(i==0){
hijo1(tuberia1,tuberia2);
exit(EXIT_SUCCESS);
}
if(i==1){
hijo2(tuberia1,tuberia2);
exit(EXIT_SUCCESS);
}
}
if(hijo > 0){
//padre nada!
}
}
for(i=0;i<2;i++){
wait(NULL);
}
}
Bien ahora vamos a especificar lo que hacen las funciones hijo1 e hijo2. La función hijo 1 recibe las dos tuberías comentadas anteriormente y lo primero que hace cerrar las partes de dichas tuberías que no utilizará. Después escribe en la tubería 1 la cadena PING y entra en un bucle en el cual repetirá el proceso 9 veces más, quedando a la escucha del recibir el PONG. Por otro lado la función hijo2 lo primero que hace es cerrar las partes de las tuberías que no utilizará y queda a la espera de recibir el PING para realizar el PONG, todo ello dentro del bucle.

int   count = 0;
close(pipe[0]);
//control errores
close(pipe2[1]);
//control errores
write(pipe[1],ping,strlen(ping));
count++;
while(count<10){
read(pipe2[0],buf,sizeof(buf)); //espera del pong!
printf(“%s\n”,buf); //imprimo lo que reciba
if((strcmp(buf,pong))==0){ //si recibo un pong!
write(pipe[1],ping,strlen(ping)); //escribe un ping!
count++;
}
}
}
void hijo2(int pipe[2], int pipe2[2]){
char buf[4096];
int count = 0;
close(pipe[1]);
//control errores
close(pipe2[0]);
//control errores
while(count<10){
read(pipe[0],buf,sizeof(buf));
if((strcmp(buf,ping))==0){
printf(“%s\n”,buf);
write(pipe2[1],pong,strlen(pong));
count++;
}
}
}

Con este ejercicio aprendíamos a entender bien el funcionamiento de los pipes. El siguiente paso era utilizar la llamada al sistema dup2 para duplicar una entrada o salida estándar y ejecutar ciertos comandos obteniendo las salidas o entradas en dicho binario, pero esto lo podremos ver más adelante…
Saludos!

1 comentario:

  1. Como os dije, el viernes estaria atento a esta entrada del blog, lo que no me imagine que lo sacarais a esta hora jajaGracias por este ejemplo, me habeis aclarado dudas :)

    ResponderEliminar