COMUNICACIÓN ENTRE PROCESOS SEGUN IPC SYSTEM V La utilización de tuberías o FIFO a veces no es suficiente, porque se necesita compartir un gran número de datos o por que se precisa una mayor velocidad. Para ofrecer mayor flexibilidad que las FIFO, el estándar de UNIX SYSTEM V desarrollado por AT&T planteó varios herramientas para IPC que suelen estar presentes en todos los sistemas UNIX/Linux. Hoy en día son poco utilizado, siendo sustituidos por mecanismos basados en sockets y procesos basados en hilos Tienen un grave inconveniente: son menos transparentes ( no se pueden tratar como archivos) y son más difíciles de programa que las pipe o fifos y más limitados que los sockets. Cada objeto IPC tiene un número que le identifica, son objetos que están en memoria principal y desaparecen cada vea que el equipo se reinicia. Se manejan mediante funciones especificas. Un proceso que trabaje con la entrada y salida estándar puede mediante redirección trabajar con pipe, fifos o sockets pero con estos mecanismos IPC Sys V. MECANISMOS IPC SYSTEM V b) Memoria compartida : Permite que procesos normales puedan compartir datos de forma parecida a los hilos. Funciones: shmget, shmat, shmdt, shmctl a) Paso de mensajes : Permite en envío y recepción de información mediante la gestión de colas de mensajes. msgget, Funciones: msgctl, msgsnd, msgrcv c) Semáforos : Mecanismo básico de sincronización se utiliza para acceder ordenadamente a la memoria compartida o para controlar cualquier otro recurso compartido: ficheros, dispositivos, etc. del sistema. Funciones: semget, semop, semctl Cada mecanismo IPC tiene un identificador propio, con sus propios permisos de lectura y escritura. Una vez creados se mantienen en la memoria principal del sistema, aunque no existan ningún proceso trabajando sobre ellos. Desaparecen automáticamente al apagar el sistema o cuando un determinado proceso decide eliminarlos. No vuelven a crearse a no ser que algún programa lo indique. Comandos básicos relacionados: $ipcs -- Muestra los Mecanismos creados en el IPC en el sistema $ipcrm -- Elimina mecanismo IPC del sistema MEMORIA COMPARTIDA • int shmget(key_t key, int size, int shmflg); Asigna un segmento de memoria compartida ( Crea o comprueba su existencia ) Comportamiento: fork() Después de un fork() el hijo hereda los segmentos de memoria compartida unidos. exec() Después de un exec() todos los segmentos de memoria compartida unidos son separados (no destruidos). exit() A través de exit() todos los segmentos de memoria compartida unidos son separados (no destruidos). Devuelve: El identificador IPC (shmid) o -1 si error • void *shmat ( int shmid, const void *shmaddr, int shmflg ) Se engancha a un segmento de memoria compartida, el parámetro shmflg puede ser 0 (Se engancha para realizar operaciones de lectura y escritura) o SHM_RDONLY (Sólo puede leer no modificar). Devuelve: -1 o Un puntero a la zona de memoria • int shmdt ( const void *shmaddr) Se desengancha de un segmento de memoria compartida. Devuelve 0 si éxito o –1 si fallo. • int shmctl(int shmid, int cmd, struct shmid_ds *buf) Operaciones de control sobre un segmento de memoria ( Borrar, consultar o modificar la propiedades ) Valores posibles de cmd: IPC_SET (modificar) , IPC_STAT (consultar) IPC_RMID ( borrar) Devuelve: 0 o -1 COLAS DE MENSAJES: Es similar al uso que podemos dar a una FIFO, pero no está asociado a un fichero sino a una lista encadenada de mensaje. Se conserva los límites de cada mensaje y el orden de recuperación no tiene que ser exclusivamente FIFO (First input First output) si no que se puede alterarse y recuperar mensajes en distintos ordenes. La cola de mensajes es una lista encadenada de mensaje con prioridades Crear una cola de mensajes: msgget - devuelve el identificador para una cola de mensajes int msgget ( key_t key, int msgflg ) Operaciones con mensajes: int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz,int msgflg ) Enviar mensaje int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg ) Recibir mensaje Formato del los mensajes: struct msgbuf { long mtype; /* tipo de msj., debe ser > 0 */ char mtext[1]; /* datos del mensaje, mínimo un byte de información */ }; Los parámetros msgflg y msgtyp permiten recuperar mensajes según prioridades: • • • 0, entonces se lee el mensaje en la parte frontal de la cola. >0 (Mayor que 0), entonces se lee el primer mensaje en la cola del tipo msgtyp, si MSG_EXCEPT no está contenido en el argumento msgflg, de otro modo se lee el primer mensaje en la cola de tipo distinto a msgtyp. <0 (Menor que 0), entonces se leerá el primer mensaje en la cola con el tipo más bajo menor o igual al valor absoluto de msgtyp. SEMAFOROS Un semáforo es una estructura de sincronización que en general no sirve directamente para intercambiar información, sino para sincronizar procesos cuando acceden a un recurso compartido. Se utiliza habitualmente junto a la memoria compartida para controla su acceso concurrente. Funcionamiento básico: • • • • • • • Un semáforo no puede tener valores negativos Sobre un semáforo sólo puede actuar un proceso cada vez Si el valor del semáforo = 0 , Significa que el recurso ocupado y cualquier proceso que intente decrementar el semáforo se quedará bloqueado Si el valor del semáforo >= 1, Significa que el recurso está libre Incrementar el valor del semáforo, Significa liberar el recurso Decrementar el valor del semáforo, Significa bloqueo el uso del recurso Si un proceso está bloqueado por que ha intentado decrementar el valor del semáforo cuando este valía 0, y otro proceso libera el recursos ( semáforo++), el proceso se despertará automáticamente y decrementará el semáforo ( semáforo--) quedando de nuevo su valor a 0 continuando con su ejecución. las funciones semget, semctl, semop, trabajan sobre array de semáforos en vez de semáforos individuales. • int semget (key_t, int numsema, int flags) Asigna un grupo de semáforos ( Crea o comprueba su existencia ) Devuelve: -1 si error o el identificador de semáforo. • int semop (int semid, struct sembuf *semops, unsigned int nops ) Realiza las operaciones descritas en la variable semops, sobre un total de nops semáforos del grupo de semáforos indicado en semid. struct semops { short sem_num; // Número de semáforo short sem_op; // Valor a asignar al semáforo short sem_flg; // Indicadores modo bloqueante o no bloqueante ( IPC_NOWAIT) } Si sem_op es positivo el valor del semáforo se incrementa Si sem_op es negativo el valor del semáforo se decrementa si el valor actual es mayor que 0, sino el proceso se bloquea a la espera. Si sem_op es cero, el proceso se queda bloqueado hasta que el valor del semáforo sea igual a 0, si ya lo es, la función retorna inmediatamente. • int semctl ( int semid, int semnum, int cmd, union semun arg ) Realiza la operación de control cmd sobre el semáforo semnum perteneciente al grupo de semáforos semid, con los argumentos arg. Algunos posibles valores de cmd. GETVAL – Obtener el valor de un semáforo SETVAL - Fijar el valor actual de un semáforo IPC_RMID – Eliminar el semáforo Consultar los ejemplos de la Web: 1.- initsema.c , Crea un grupo de semáforos de tamaño 1 y fija su valor a 1 (libre) 2.- incsema.c , Incrementa el valor del semáforo ( libera el recurso) 3.- decsema.c , Decrementa el valor del semáforo ( Bloquea el recurso) 4.- versema.c, Muestra el valor actual del semáforo.