que son las tuberias con nombre en ubuntu y algunos ejercicios
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 mkfifocomo 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: