Comunicación entre Procesos
Memoria Compartida y Semáforos POSIX

Algo de historia: Unix System V parte el año 1983 y varias versiones se crearon. La versión más exitosa fue la 4, SVR4 (System V Release 4). Esta versión de Unix incluyó los mecanismos de comunicación entre procesos que hoy se conocen como System V IPC. Posteriormente POSIX "Portable Operating System Interface" estandariza los mecanismos de IPC y crea otra API para IPC. Como SVR4 fue muy difundida y está presente en muchos sistemas actuales, POSIX incluye también el API de IPC de SVR4.

  En esta página se describe la API de POSIX posterior a SVR4 por mayor simplicidad y mejor diseño de su interfaz comparada con los llamados del sistema SVR4. Visite este material para estudiar los llamados del sistema SVR4.

Algunas estructuras de datos son creadas globalmente en el sistema, el cual no maneja un contador de referencias. La estructura permanece en el sistema hasta que es removida por un proceso o la máquina es "rebooted". (Parecido a procesos zombies). En caso de ser necesario, con los comandos ipcs e ipcrm se puede listar y remover estos mecanismos de comunicación entre procesos. 


  Memoria Compartida en POSIX
  POSIX define un API con las siguientes funciones:
    shm_open(3): crea y abre un objeto de memoria compartida nuevo, o abre una objeto existente. Es análogo a open(2).  El valor retornado es un descriptor de archivo para ser usado en los otros llamados del API.
    ftruncate(2)   Fija el tamaño del objeto de memoria compartida.  Objetos de memoria compartida recien creados tienen largo cero.
    (Los dos llamados previos en su conjunto cumplen funcionalidad similar a shmget del sistema SVR4).

    mmap(2)       Mapea el objeto de memoria compartida en el espacio de direcciones del proceso llamador. (Este llamado se puede considerar análogo a shmat de SVR4).
    munmap(2)    Desmapea el objeto de memoria compartida del espacio de direcciones del proceso llamador. (Este llamado se puede considerar análogo a shmdt de SVR4).
    shm_unlink(3)  Remueve el segmento de memoria compartida del sistema de archivos (es una visión lógica, no en disco).
    close(2)       Cierra el descriptor de archivo retornado por shm_open(3). El proceso hace este llamado cuando deja de necesitar el descriptor.
    fstat(2)       Obtiene el estado del segmento de memoria compartida. Entre la información retornada está: el tamaño del objeto, sus permisos, dueño y grupo.
    fchown(2)      Para cambiar el dueño del segmento de memoria compartida.
    fchmod(2)      Para cambiar los permisos del objeto de memoria compartida.

Ver ejemplos aquí: Se trata de un sistema productor-consumidor sin mecanismos de sincronización.


Semáforos en POSIX

Un semáforo es un entero cuyo valor nunca baja de cero y su modificación se desarrolla de manera atómica, es decir, no hay cambios de contextos ni interrupciones durante su modificación. Las siguientes operaciones pueden modificar ese valor entero: sem_post() para incrementar el valor en uno y sem_wait() para reducirlo en uno. Si el valor de un semáforo ya es cero, entonces sem_wait() se bloquea hasta que el semáforo toma un valor sobre cero.

Si bien POSIX define un conjunto de llamados para manejar semáforos, su implentación no está tan difundida como aquella de SVR4. De man sem_overview se tiene:"System  V  semaphores (semget(2), semop(2), etc.) are an older semaphore API.  POSIX semaphores provide a simpler, and better designed interface than System V semaphores; on the other hand POSIX semaphores are less widely available (especially on older systems) than System V semaphores."

Los Semáforos POSIX viene en dos tipos: Semáforos con nombre (named semaphores) y sin nombre (unnamed semaphores).

Los semáforos con nombre son identificados con un string de la forma "/algún_nombre". Varios procesos pueden operar sobre el mismo semáforo usando el mismo nombre en el llamado a sem_open().

Los semáforos sin nombre no tienen string que los identifique. En este caso el semáforo debe ser puesto en una zona de memoria de acceso común a varias hebras o procesos relacionados. Éstos no pueden ser usados por procesos no relacionados entre sí.

POSIX define un API para el manejo de semáforos, para mayor información revisar páginas man de:

sem_open(3): Crea un semáforo.

sem_close(3): Cierra un semáforo.

sem_unlink(3): remueve el semáforo.

sem_wait(3): decrementa en uno el valor del semáforo si éste es mayor que 0, si el valor del semáforo es cero, sem_wait se bloquea hasta que el semáforo sea mayor que cero.

sem_post(3): incrementa el valor del semáforo.

Otros llamados son: sem_destroy(3), sem_getvalue(3), sem_init(3).

Vea este ejemplo productor consumidor empleando memoria compartida y semáforos POSIX. El diagrama de arquitectura simplificado se este ejemplo se muestra en la figura 1.

Figura 1: Diagrama ejemplo Productor/Consumidor