No es un bug, es una característica no documentada

lunes, 5 de octubre de 2015

Servicios y procesos. Servicios en C (III). FIFO

Las PIPE en principio solo sirven para comunicaciones padre – hijo, por lo que para comunicarnos entre procesos independientes necesitamos otro tipo estructura.

Esta son los FIFO, archivos que ya no se crean en el proceso padre, sino que lo genera el sistema operativo. Es un ente que genera el SO y que podrá ser utilizado por diversos procesos estén o no emparentados.
Es decir, los mecanismos de comunicación no tienen que estar necesariamente emparentados.

Se llama FIFO porque es una cola (first in, first out).

Para operar con ellos en C usaremos comandos de ficheros de bajo nivel (write, open…)

El comando que permite crear una FIFO se mknod, al igual que la función de C que permite generarlas en ese lenguaje.

En Linux, el comando para generar un FIFO sigue esta estructura:

mknod [opciones] nombreFichero p


Con el parámetro mode indicamos los permisos que tendrá nuestro FIFO.
Una vez generado podemos comprobarlos haciendo un ls-l


Hecho esto, y sabiendo que funciona como una pila, podemos meterle información para que lo vaya leyendo otro proceso que acceda al FIFO.

Vamos a introducirle el contenido de visualizar los directorios, con un ls, para luego visualizar por pantalla su contenido con un cat.


En C podemos programar nuestros procesos para que mientras uno crea y está a la escucha para leer el FIFO, otro introduzca información en él y sea leído por el primero.

Para ello usaremos la función mknod (tiene el mismo nombre que el comando usado para generar el fichero).

La función mknod tiene la siguiente estructura:

int mknod (const char *pathname, mode_t modo, dev_t dev);

Donde:
  • Pathname: Nombre del dispositivo
  • Modo: Especifica tanto los permisos de uso como el tipo de nodo que se creará
  • Dev: Debe ser una combinación (utilizando OR bit a bit) de uno de los tipos de fichero que se enumeran a continuación.
    • S_IFREG
    • S_IFCHR
    • S_IFBLK
    • S_IFIFO – Para crear un FIFO
El código para la creación y lectura de un FIFO es el siguiente
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(void){
     
     int fp;
     int p, bytesLeidos;
     char saludo[] = "Un saludo!!!\n", buffer[10];
     
     p = mknod("FIFO3", S_IFIFO|0666, 0); // Permiso de lectura y escritura
     
     if (p == -1){
          printf("Ha ocurrido un error \n");
          exit(0);
     }
     
     while(1){
          fp = open("FIFO3", 0);
          bytesLeidos = read(fp, buffer, 1);
          printf("Obteniendo información... \n");
          while(bytesLeidos != 0){
                printf("%s", buffer);
                bytesLeidos = read(fp, buffer, 1); // lee otro byte
          }
          close(fp);
     }
     
     return 0;
}
Y el programa para escribir en el FIFO:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
     
     int fp;
     char saludo[] = "Un saludo!!!\n";
     fp = open("FIFO3", 1); // Abre el fichero FIFO ya creado
     
     if(fp == -1){
          printf("Error al abrir el fichero...\n");
          exit(1);
     }
     
     printf("Mandando información al FIFO...\n");
     write(fp, saludo, strlen(saludo)); // Manda al FIFO fp la cadena de texto saludo con los caracteres contados por strlen
     
     close(fp);
     return 0;
}
Para comprobar el funcionamiento compilamos y ejecutamos primero el programa para la lectura (es el que crea el FIFO) y se mantiene a la espera.

Mientras, abrimos otra terminal y lanzamos el programa para escribir en el FIFO.
Podremos ver el desarrollo en tiempo real, siendo algo tal que así



Al mostrar el texto por pantalla lo vemos de esta forma porque uno trabaja en ASCII y otro en UNICODE, pero para hacernos una idea de que se comunican correctamente sirve.

Ejercicio. Creamos tres procesos que van a interactuar con un FIFO. Uno de ellos va a meter números al FIFO, y los otros dos estarán para leerlos. Un proceso de lectura deberá sacar por pantalla los números pares y el otro se encargará de los impares.

0 comentarios:

Publicar un comentario