Pipes con nombre:
Los
pipes (tuberías) con nombre son una vía de intercambio de datos. Igual que los
pipes estudiados se gestionan mediante el método FIFO, es decir, el primer byte
introducido por el emisor será el primer byte en ser extraído por el receptor.
Las tuberías con nombre también reciben el nombre de FIFOs. También son una vía de comunicación unidireccional como los
pipes.
Diferencias
con los pipes:
¨
Tienen un
nombre, ocupando una entrada en el sistema deficheros. Se accede a él mediante
un nombre de camino, igual que un fichero (se puede ver con la orden ls).
¨
Pueden
intercomunicar procesos sin ningún tipo de relación, es decir, no tienen que
estar emparentados como en los pipes. Esta característica permite que los FIFOs
puedan utilizarse para comunicar y sincronizar procesos de la misma máquina,
sin necesidad de que lo hereden por medio de la llamada fork.
¨
Existen hasta
que son borrados explícitamente como cualquier fichero.
Creación:
Hay
varias formas de crear un FIFO. Se puede crear mediante mkfifo o bien mediante mknod. Tanto mkfifo
como mknod se pueden utilizar desde la línea de órdenes o bien
llamando al servicio correspondiente, como se detalla a continuación:
¨
mkfifo en la
línea de órdenes:
mkfifo –m=modo_de_acceso nombre
modo_de_acceso representa los permisos asociados al FIFO. Por
ejemplo:
mkfifo –m=660 mififo
o
mkfifo –m=”u+g=rw” mififo
donde
se está creando un FIFO de nombre mi mififo con permisos de acceso para el usuario y para el
grupo de lectura y escritura.
¨
Servicio
mkfifo:
El
prototipo del servicio que permite crear una tubería con nombre es el
siguiente:
int mkfifo( char *nombre, mode_t mode);
Los
parámetros proporcionados son el nombre del FIFO y los permisos asociados. La
llamada devuelve 0 si se ejecutó con éxito o –1 en caso de error. Por ejemplo:
Resultado= mkfifo(mififo,
660);
Crea
el FIFO de nombre mififo con permisos de lectura y
escritura para el usuario y el grupo.
¨
mknod en la
línea de órdenes:
mknod sirve para crear ficheros especiales. Un FIFO es
considerado un fichero especial.
mknod –m=modo_de_acceso nombre
tipo_fich_especial
Se
indica el nombre, los permisos y el tipo de fichero especial, que para la
creación de un FIFO debe ser p indicando que
es un pipe. Por ejemplo:
mknod –m=660 mififo p
¨
Servicio
mknod:
El
prototipo de este servicio es el siguiente:
int mknod( char *nombre, mode_t mode, dev_t
dev);
Los
parámetros proporcionados son el nombre del FIFO y el modo de acceso incluyendo
los permisos (para un FIFO se debe indicar S_IFIFO), el tercer parámetro en un FIFO es ignorado. La
llamada devuelve 0 si se ejecutó con éxito o –1 en caso de error. Por ejemplo:
Resultado= mknod(mififo,
S_IFIFO|660, 0);
Crea
el FIFO de nombre mififo con permisos de lectura y
escritura para el usuario y el grupo.
Una
vez creada una tubería con nombre se utiliza exactamente como un fichero.
Recordamos a continuación los servicios utilizados:
Apertura:
Se
utiliza el servicio open. Su prototipo
es el siguiente:
int open(char *nombre, int flag);
El
primer argumento indica el nombre del FIFO y el segundo la forma en la que se va a acceder. Los posibles
valores de flag son los siguientes:
O_RDONLY: se abre sólo para realizar operaciones de lectura.
O_WRONLY: se abre sólo para realizar operaciones de
escritura.
O_RDWR: se obre para realizar operaciones de lectura y
escritura.
El
servicio open devuelve un descriptor de
archivo que se puede utilizar para leer y escribir del FIFO. En el caso de
error devuelve –1. La llamada open bloquea al
proceso que la ejecuta hasta que haya algún otro proceso en el otro extremo del
FIFO. Si no interesa este comportamiento, se puede usar la bandera O_NONBLOCK en la llamada a open para desactivar esta opción por defecto.
Cierre:
Para
cerrar un FIFO se utiliza el servicio close. Su prototipo es el siguiente:
int close(int fd);
El
argumento es el descriptor del archivo que se quiere cerrar, en este caso, el
descriptor del FIFO devuelto en la apertura. La llamada devuelve 0 si se
ejecutó con éxito o –1 en caso de error.
Lectura:
Para
leer de un FIFO se utiliza read. El prototipo
es el siguiente:
int
read(int fd, char *buffer, int n);
El
primer argumento es el descriptor del FIFO. El segundo argumento es la
dirección del buffer de usuario donde se van a guardar los datos leídos. El
último argumento es el número de bytes que se quieren leer. La llamada devuelve
el número de bytes leídos o –1 en caso de error.
Escritura:
Para
escribir en un FIFO se utiliza write. El
prototipo es el siguiente:
int
write(int fd, char *buffer, int n);
El
primer argumento representa el descriptor de archivo del FIFO. El segundo
argumento especifica el buffer de usuario donde se encuentran los datos que se
van a escribir al FIFO. El último argumento indica el número de bytes a
escribir.
Una
tubería debe tener un lector y un escritor. Si un proceso trata de escribir en
una tubería que no tiene lectores asociados, el núcleo enviará la señal SIGPIPE.
NOTA:
también se pueden utilizar las funciones fopen, fclose, fputs, fgets … que
utilizan FILE * en vez de int para indicar un fichero.
Borrado:
El
prototipo del servicio utilizado para borrar un FIFO es:
int unlink(char *fifo);
Esta
llamada pospone la destrucción del FIFO hasta que todos los procesos que lo
estén utilizando lo hayan cerrado con la función close.
Para
borrar una tubería con nombre también se pueden utilizar la orden
correspondiente del sistema operativo para el borrado de ficheros (rm).
Ejemplo: El siguiente programa crea un fifo de nombre
mififo. En cada iteración del bucle lee una cadena enviada por el proceso
escritor:
0 comentarios:
Publicar un comentario