Mecanismos de IPC's. Pipes

Documentos relacionados
Sistemas Operativos: Programación de Sistemas. Curso Oscar Déniz Suárez Alexis Quesada Arencibia Francisco J.

IPC SYSTEM V. Técnicas Digitales III Ing. Gustavo Nudelman Universidad Tecnológica Nacional - Facultad Regional Buenos Aires

Mecanismos IPC System V

Comunicación entre Procesos

Los semáforos en Unix

Memoria Compartida. Llave de acceso. Segmento Compartido. estructura definida en A. estructura definida en B. Proceso B. Proceso A

Prácticas de Sistemas Operativos

Prácticas de Sistemas Operativos

Seguridad en el Sistema de Archivos. Dr. Alonso Ramírez Manzanares 23-Nov-2010

System V MENSAJES. Francisco Javier Montero Vega Francisco García Rodríguez DSO

Prácticas de Sistemas operativos

Prácticas de Sistemas operativos

Taller de Sistemas Operativos. Linux Programming Interface Inter Process Communication (IPC)

Redirecciones y Tuberías

IPC Repaso: Procesos

Boletín 3- Archivos. Departamento de Lenguajes y Sistemas Informáticos

Unidad de Arquitectura de Ordenadores y Sistemas Operativos. Shared Memory & Semaphores

Sistemas Operativos: Programación de Sistemas. Curso Oscar Déniz Suárez Alexis Quesada Arencibia Francisco J.

Laboratorio de Sistemas Operativos

PRÁCTICAS DE APLICACIONES DISTRIBUIDAS EN EQUIPO. Introducción: Cada práctica con lleva una previa investigación, la cual debe realizar cada equipo.

Prácticas de Sistemas operativos

Prácticas de Sistemas operativos

Mensajes LECCIÓN 21: MENSAJES

Parte Práctica Adicional del Coloquio o Examen Final de Sistemas Operativos 2014.

Memoria Compartida. Por: Samuel Díaz Cabrera

Formatos para prácticas de laboratorio

Práctica 2. Teoría. Memoria Compartida y Semáforos

Funciones POSIX (I): Introducción

COMUNICACIÓN ENTRE PROCESOS

Computación de Alta Performance Curso 2009 PROGRAMACIÓN PARALELA EN LENGUAJE C

Sistemas Operativos I. Enxeñería Informática. Curso 2007/08. Práctica 2: Concurrencia de procesos: Productores/Consumidores.

Práctica 1: Intérprete de mandatos. Sistemas Operativos Área de Arquitectura y Tecnología de Computadores

Biblioteca de sistema

MC Hilda Castillo Zacatelco PROCESOS

Sistemas Operativos sesión 12: tuberías

Bloque I: Principios de sistemas operativos

Boletín 4- Procesos. Departamento de Lenguajes y Sistemas Informáticos

Boletín 4- Procesos. Departamento de Lenguajes y Sistemas Informáticos

Entrada y Salida de Archivos

Examen de Laboratorio de Sistemas Operativos. Primera Convocatoria. 2007/2008. Tercero Ingeniería Informática. Apellidos: 18 de Junio de 2008

Plataformas de Tiempo Real

SISTEMAS OPERATIVOS I. CURSO 2010/11. PRÁCTICA 2: Problema de los Productores/Consumidores (concurrencia de procesos)

Práctica 1 Programación de Aplicaciones Distribuidas: Sockets UDP. Laboratorio de Comunicación de Datos ITT Telemática Septiembre 2011

PROGRAMACIÓN CON LLAMADAS AL SISTEMA POSIX (INTRODUCCIÓN A LA PROGRAMACIÓN CON UNIX/LINUX)

Punto muerto-interbloqueo

Clases 04 y 05: Repaso de programación de sistemas basados en UNIX

Ejercicios sobre tuberías

Apartado a.- Obtenga un listado de todos los ficheros regulares del sistema terminados en.y ó.c, con permiso de lectura para el grupo.

UNIVERSIDAD AUTONOMA DE BAJA CALIFORNIA FACULTAD DE INGENIERIA MANUAL DE PRACTICAS DE APLICACIONES DISTRIBUIDAS

Ficheros y Directorios

Funciones POSIX III Funciones POSIX III. No Nombrados Nombrados. sem_open sem_open. sem_close sem_close. sem_unlink sem_unlink

Sistemas Operativos. Eloy Anguiano Rey Rosa M. Carro Ana González

Examen Final de SO Grau

Sistemas Operativos Ingeniería de telecomunicaciones Sesión 3: Concurrencia

Introducción a Sistemas Operativos: Ficheros

Analista Universtiario en Sistemas. Sistemas Operativos. IPC - Sockets SOCKETS

Procesamiento de Archivos

Memoria compartida y semáforos r/w. La página del manual que podría servir para describir estas funciones es la siguiente:

Sistemas operativos: una visión aplicada. Capítulo 5 Comunicación y sincronización de procesos

Ejercicio Sockets Suma Resta. Descripción

Introducción a Sistemas Operativos: Concurrencia

Semáforos. Eloy García Martínez Lorena Ascensión Olivero

Ejercicios de la sesión 4 de C resueltos

INTRODUCCIÓN A LAS LLAMADAS AL SISTEMA OPERATIVO UNIX

Capitulo VI Arquitectura del sistema de archivos

El tiempo de búsqueda es de 3 + 0,04 x ms, siendo x el número de cilindros a recorrer.

Programación I Teoría : Entrada/Salida - Archivos.

Tema 13: Manejo de archivos en lenguaje C

API del SO + Comunicación entre procesos (IPC)

Tema 4: Modelos Teóricos de Control de la Concurrencia

Llamadas al sistema básicas de control de procesos

Resuelva con una orden UNIX las siguientes tareas:

Paso de mensajes. Gustavo Romero López. 15 de mayo de Arquitectura y Tecnología de Computadores

Archivos de números. Tema 10c. Archivos de números. Archivos de números. Archivos mixtos. Archivos mixtos. Manejo de archivos de datos en C

Concurrencia, exclusión mutua y sincronización. Capítulo 5 HungriaBerbesi

Para C un chero no es más que una porción de almacenamiento

Introducción a Sistemas Operativos: Comunicación entre Procesos

Procesos. Aspectos básicos

Universidad Simón Bolívar Departamento de Computación y Tecnología de la Información Curso de Redes I CI-4815 Trimestre Septiembre Diciembre 2013

Tema 4: Gestión de Procesos

Programación de Sistemas. Programación de Sistemas con Ansi C sobre UNIX. Gestión de errores. Gestión de errores. Ficheros regulares

Estructuras y funciones de programación de sockets.

REPRESENTACIÓN INTERNA DE FICHEROS

Lenguaje C. República Bolivariana de Venezuela Fundación Misión Sucre Aldea Fray Pedro de Agreda Introducción a la Programación III

[Cuestión 1.]Resuelva con una orden UNIX las siguientes tareas:

Archivos & Cadenas CURSO DE PROGRAMACIÓN EN C. Centro de Investigación y de Estudios Avanzados del IPN. CINVESTAV - Tamaulipas.

Prácticas de Sistemas operativos

Lenguaje de Programación: C++ ARCHIVOS I/O

Introducción a Sistemas Operativos: Ficheros

Aplicación Multiproceso sobre HTTP Ejemplo -

MANEJO DEL SISTEMA DE ARCHIVOS

Concepto Concept s Los L nom res re d e e los h c eros: exter te n r os o o fí s fí ico nom re ú nico i del del ar chiv chiv o o o ficher ficher en

SISTEMAS OPERATIVOS: INTRODUCCIÓN Y CONCEPTOS BÁSICOS. Servicios del Sistema Operativo

Comunicación entre procesos (IPC) (+ Continuación API del SO)

Redes de Computadores Nivel de Aplicación: Programación con sockets 3

Examen Final de Teoría. Grupo de teoría:

Transcripción:

Mecanismos de IPC's Para la comunicación entre procesos se disponen de varios mecanismos: Pipes Named Pipes (FIFOS) File Locking System V IPC's Message queues Semaphores Shared Memory Mem. Mapped Files Sockets De estos mecanismos se desarrollan en este documento todos con excepción de File locking, Mapped Files y Sockets; los dos primeros no se dictan en esta cátedra y el tercero se trata en otra clase. Pipes Básicamente la función pipe() retorna un par de descriptores de archivos. Uno de esos descriptores es para escribir y el otro es para leer el pipe. Lo que se escribe por el descriptor de escritura se lee en el otro. #include <unistd.h> int pipe(int descf[2]); Ejemplo #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> int main(void) int pfds[2]; char buf[30]; if (pipe(pfds) == -1) perror("pipe"); printf("escribiendo al descriptor #%d\n", pfds[1]); write(pfds[1], "test\0", 5); printf("leyendo desde el descriptor #%d\n", pfds[0]);

read(pfds[0], buf, 5); printf("leí \"%s\"\n", buf); Este mecanismo tiene una dificultad importante, ambos descriptores son conocidos por el proceso que crea el pipe, no hay manera que otro proceso conozca estos valores a menos que sea un proceso creado por este utilizando fork() por ejemplo. Named Pipes (FIFOS) Son similares a los pipes con excepción que estos tienen nombre, con lo cual distintos procesos pueden accederlos para lectura o escritura como si fueran archivos. Hay dos formas de crear un FIFO. Mediante línea de comando mknod: mdoallo@guri:~$ mknod pepe p mdoallo@guri:~$ ls -l pepe prw-r--r-- 1 mdoallo mdoallo 0 sep 14 23:15 pepe O bien crearlo directamente en el código de un programa mediante la función mknod(). #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int mknod(const char *pathname, mode_t mode, dev_t dev); mknod intenta crear en el sistema de ficheros un nodo-i de tipo tubería nombrada (o FIFO) llamado pathname, especificado por mode y dev. Un nodo-i (o i-node) referencia a un archivo en Linux, estos pueden ser archivos normales (archivo propiamente dicho, carpetas o enlaces), un archivo especial de caracteres (Device Char Driver) que permite comunicar al sistema operativo con dispositivos de tipo carácter, un archivo especial de bloques; o bien, una tubería nombrada. mode especifica tanto los permisos de uso del nodo-i a crear como su tipo. Debe ser una combinación (mediante un O-lógico) de uno de los tipos de ficheros enumerados a continuación y de los permisos para el nuevo nodo-i. El tipo de fichero debe ser uno de los siguientes: S_IFREG, para especificar un fichero normal (que será creado vacío); S_IFCHR, un fichero especial de caracteres; S_IFBLK, un fichero especial de bloques; S_IFIFO, FIFO (tubería con nombre), o cero, lo que creará un fichero normal. En este caso se usa S_IFIFO. Si el tipo de fichero es S_IFCHR o S_IFBLK entonces dev especifica los números mayor y menor del fichero especial de dispositivo creado; en caso contrario, es ignorado. Entonces ponemos 0.

Ejemplo de programa productor de información para un FIFO: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #define FIFO_NAME "canio_canion" int main(void) char s[300]; int num, fd; mknod(fifo_name, S_IFIFO 0666, 0); printf("esperando por lectores...\n"); fd = open(fifo_name, O_WRONLY); printf("conseguí un lector tipea algo \n"); while (gets(s),!feof(stdin)) if ((num = write(fd, s, strlen(s))) == -1) perror("write"); else printf("se enviaron %d bytes.\n", num); Ahora para probar este programa hace falta alguien que lo lea, pues es suficiente con hacer: $ cat canio_canion Otro ejemplo de programa consumidor de información de un FIFO: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #define FIFO_NAME "canio_canion" int main(void) char s[300]; int num, fd;

mknod(fifo_name, S_IFIFO 0666, 0); printf("esperando escritores...\n"); fd = open(fifo_name, O_RDONLY); printf("conseguí un escritor\n"); do if ((num = read(fd, s, 300)) == -1) perror("read"); else s[num] = '\0'; printf("se recibieron %d bytes: \"%s\"\n", num, s); while (num > 0); Nótese que en ambos la función open() en bloqueante, a menos que se utilice el flag O_NDELAY. Message queues Pipes y FIFO's permiten comunicación entre dos procesos, un emisor y otro receptor; no hay forma de alterar el orden en que la información se recibe (concepto FIFO), ni que intervengan múltiples procesos. Message queues es un sistema de comunicación entre procesos superior a lo visto hasta el momento. Permite crear estructuras de información, asignarles etiquetas, disponer de múltiples emisores y múltiples receptores de información; además, cada proceso receptor puede leer sólo las etiquetas que son de su interés. La forma de operar es la siguiente: Primero se crea la cola de mensajes (message queue), luego los procesos se conectan a la cola para escribir o leer mensajes de la misma; finalmente se borra la cola. El comando de consola ipcs permite ver el estado de una cola. El comando ipcrm permite borrar colas. Para crear la cola primero hay que general una clave por medio de la función ftok(). # include <sys/types.h> # include <sys/ipc.h> key_t ftok ( char *camino, int proy ) La función ftok utiliza la identidad del fichero que indica camino (que debe referirse a un fichero existente y accesible) y los 8 bits menos significativos de proy (que debe ser distinto de cero) para generar una clave IPC de System V de tipo key_t, adecuada para el uso con msgget(), semget(), o shmget(). El valor resultante es el mismo para todos los nombres de ruta que hacen referencia al mismo fichero, cuando se utiliza el mismo valor de proy. El valor devuelto debería ser diferente cuando los ficheros (que existen simultáneamente) o los identificadores de proyecto son distintos.

En caso de éxito se devuelve la clave key_t generada. En caso de fallo se devuelve -1, y la variable errno indica el error al igual que con la llamada al sistema stat(2). Luego de creada la clave se puede crear la cola con la función msgget() #include <sys/msg.h> int msgget(key_t key, int msgflg); La función devuelve el identificador de la cola de mensajes asociada a key. Se crea una nueva cola de mensajes si msgflg tiene el valor IPC_CREAT. En la creación, los 9 bits más bajos del argumento msgflg definen los permisos de acceso a la cola de mensajes. Estos bits para los permisos tienen la misma forma y semántica que los de los permisos de acceso en las llamadas al sistema open(2) o creat(2) (Los permisos de ejecución no son usados.) Qué se envía o recibe en una cola? Para enviar se utiliza la función msgsnd(). #include <sys/msg.h> int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg); Para enviar o recibir un mensaje, el proceso invocador reserva una estructura de la siguiente manera genérica: struct msgbuf long mtype; /* tipo de msj., debe ser > 0 */ char mtext[1]; /* datos del mensaje */ ; El campo msgbuf es una estructura cuyo tamaño viene determinado por msgsz, un valor entero no negativo. Los mensajes de longitud cero (p.e., sin campo mtext) están permitidos. El campo mtype debe tener un valor entero estrictamente positivo que puede ser empleado por el proceso receptor para la selección de mensaje (vea la sección sobre msgrcv). El argumento msgsz especifica el tamaño máximo en bytes para el miembro mtext de la estructura apuntada por el argumento msgp. Si el texto del mensaje tiene una longitud mayor de msgsz, entonces si el argumento msgflg contiene MSG_NOERROR, el texto del mensaje se truncará (y la parte truncada se perderá), y si no, el mensaje no se borra de la cola y la llamada al sistema falla regresando y poniendo el valor E2BIG en errno.

Ejemplos de estructuras struct msgbuf long mtype; char mtext[1]; ; Otro: struct pirate_msgbuf long mtype; /* must be positive */ struct pirate_info char name[30]; char ship_type; int notoriety; int cruelty; int booty_value; info; ; Otro: struct cheese_msgbuf ; long mtype; char name[20]; int type; float yumminess; /* calculate the size of the data to send: */ int size = sizeof(struct cheese_msgbuf) - offsetof(struct cheese_msgbuf, name); Ejemplo de envío de mensajes #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/msg.h> struct my_msgbuf long mtype; char mtext[200]; ; int main(void) struct my_msgbuf buf; int msqid;

key_t key; if ((key = ftok("msg_tx.c", 'B')) == -1) perror("ftok"); if ((msqid = msgget(key, 0644 IPC_CREAT)) == -1) perror("msgget"); printf("enter lines of text, ^D to quit:\n"); buf.mtype = 1; /* we don't really care in this case */ while(fgets(buf.mtext, sizeof buf.mtext, stdin)!= NULL) int len = strlen(buf.mtext); /* ditch newline at end, if it exists */ if (buf.mtext[len-1] == '\n') buf.mtext[len-1] = '\0'; if (msgsnd(msqid, &buf, len+1, 0) == -1) /* +1 for '\0' */ perror("msgsnd"); if (msgctl(msqid, IPC_RMID, NULL) == -1) perror("msgctl"); Ejemplo de recepción de mensajes #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/msg.h> struct my_msgbuf long mtype; char mtext[200]; ; int main(void) struct my_msgbuf buf; int msqid; key_t key; if ((key = ftok("msg_tx.c", 'B')) == -1) /* same key as kirk.c */

perror("ftok"); if ((msqid = msgget(key, 0644)) == -1) /* connect to the queue */ perror("msgget"); printf("listo para recibir mensajes.\n"); for(;;) /* Nunca sale! */ if (msgrcv(msqid, &buf, sizeof(buf.mtext), 0, 0) == -1) perror("msgrcv"); printf("recibí: \"%s\"\n", buf.mtext); Semaphores Los semáforos permiten que procesos sincronicen su ejecución, no intercambian información, si no que permiten que un proceso espere hasta que otro proceso termine una determinada tarea. La forma de utilizarlos es similar a las colas de mensajes, por cuanto hay que generar una clave con ftok() y luego se crea el semáforo (o se vincula a un semáforo existente) por medio de la función semget(). Luego el semáforo es un contador que se opera con la función semctl(). #include <sys/sem.h> int semget(key_t key, int nsems, int semflg); Esta función devuelve el identificador del conjunto de semáforos asociado con el argumento key. Un nuevo conjunto de nsems semáforos se crea si msgflg tiene el valor IPC_CREAT. Con el ID de semáforo ahora se lo controla con semctl(). #include <sys/sem.h> int semctl(int semid, int semnum, int cmd,...); La función semctl realiza la operación de control especificada por cmd sobre el conjunto de semáforos identificado por semid, o en el semáforo semnum-th de dicho conjunto. (Los semáforos

son numerados comenzando por el 0.) Esta función tiene tres o cuatro argumentos. Cuando hay cuatro, la llamada es semctl(semid,semnum,cmd,arg); donde el cuarto argumento arg tiene como tipo union semun definido como sigue: union semun int val; /* valor para SETVAL */ struct semid_ds *buf; /* buffer para IPC_STAT, IPC_SET */ unsigned short int *array; /* array para GETALL, SETALL */ struct seminfo * buf; /* buffer para IPC_INFO */ ; Los comandos se pueden leer de manpages. Ejemplo de uso de semáforos #include #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <errno.h> <sys/types.h> #include <sys/sem.h> #define MAX_RETRIES 10 union semun int val; ; struct semid_ds *buf; ushort *array; /* ** initsem() -- more-than-inspired by W. Richard Stevens' UNIX Network ** Programming 2nd edition, volume 2, lockvsem.c, page 295. */ int initsem(key_t key, int nsems) /* key from ftok() */ int i; union semun arg; struct semid_ds buf; struct sembuf sb; int semid; semid = semget(key, nsems, IPC_CREAT IPC_EXCL 0666); if (semid >= 0) /* we got it first */ sb.sem_op = 1; sb.sem_flg = 0; arg.val = 1; printf("press return\n"); getchar(); for(sb.sem_num = 0; sb.sem_num < nsems; sb.sem_num++) /* do a semop() to "free" the semaphores. */

/* this sets the sem_otime field, as needed below. */ if (semop(semid, &sb, 1) == -1) int e = errno; semctl(semid, 0, IPC_RMID); /* clean up */ errno = e; return -1; /* error, check errno */ else if (errno == EEXIST) /* someone else got it first */ int ready = 0; semid = semget(key, nsems, 0); /* get the id */ if (semid < 0) return semid; /* error, check errno */ /* wait for other process to initialize the semaphore: */ arg.buf = &buf; for(i = 0; i < MAX_RETRIES &&!ready; i++) semctl(semid, nsems-1, IPC_STAT, arg); if (arg.buf->sem_otime!= 0) ready = 1; else sleep(1); if (!ready) errno = ETIME; return -1; else return semid; /* error, check errno */ return semid; int main(void) key_t key; int semid; struct sembuf sb; sb.sem_num = 0; sb.sem_op = -1; /* set to allocate resource */ sb.sem_flg = SEM_UNDO; if ((key = ftok("sem.c", 'J')) == -1) perror("ftok"); /* grab the semaphore set created by seminit.c: */

if ((semid = initsem(key, 1)) == -1) perror("initsem"); printf("press return to lock: "); getchar(); printf("trying to lock...\n"); if (semop(semid, &sb, 1) == -1) perror("semop"); printf("locked.\n"); printf("press return to unlock: "); getchar(); sb.sem_op = 1; /* free resource */ if (semop(semid, &sb, 1) == -1) perror("semop"); printf("unlocked\n"); Shared Memory Este mecanismo permite compartir información entre procesos. Trabaja con clave igual que los semáforos y las colas de mensajes, uso de la función ftok(). Luego la memoria compartida se crea y se vincula a cada proceso interesado. Para crear se utiliza la función shmget(). #include <sys/shm.h> int shmget(key_t key, int size, int shmflg); shmget() devuelve el identificador del segmento de memoria compartida asociado con el valor del argumento key. Se crea un nuevo segmento de memoria compartida, de tamaño igual al valor de size, si shmflg tiene el valor IPC_PRIVATE crea la memoria compartida. Luego para conectarnos a la memoria se utiliza shmat(). #include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); La función shmat pega el segmento de memoria compartida identificada por shmid al espacio de direcciones del proceso que llama a la función. La dirección del pegado se especifica en shmaddr según uno de los criterios siguientes: Si shmaddr es NULL, el sistema escoge una dirección adecuada (sin utilizar) en donde pegar el segmento. El resto ver en manpages. La función shmdt despega el segmento de memoria compartida localizado en la dirección especificada por shmaddr del espacio de direcciones del proceso invocador. En caso de fallo ambas funciones devuelven -1 con errno indicando el error. En caso de éxito shmat devuelve la dirección del segmento de memoria compartido pegado, y shmdt devuelve 0. Ejemplo de uso de memoria compartida #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/shm.h> #define SHM_SIZE 1024 /* make it a 1K shared memory segment */ int main(int argc, char *argv[]) key_t key; int shmid; char *data; int mode; if (argc > 2) fprintf(stderr, "usage: shmdemo [data_to_write]\n"); /* make the key: */ if ((key = ftok("shmdemo.c", 'R')) == -1) perror("ftok"); /* connect to (and possibly create) the segment: */ if ((shmid = shmget(key, SHM_SIZE, 0644 IPC_CREAT)) == -1) perror("shmget");

/* attach to the segment to get a pointer to it: */ data = shmat(shmid, (void *)0, 0); if (data == (char *)(-1)) perror("shmat"); /* read or modify the segment, based on the command line: */ if (argc == 2) printf("escribiendo al segmento: \"%s\"\n", argv[1]); strncpy(data, argv[1], SHM_SIZE); else printf("el segmento contiene: \"%s\"\n", data); /* detach from the segment: */ if (shmdt(data) == -1) perror("shmdt"); Bibliografía Este apunte está baso en: http://beej.us/guide/bgipc manpages Apuntes de la cátedra