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>char *ping = “PING”;
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
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!
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