Comunicación entre procesos

De Departamento de Informatica
Saltar a: navegación, buscar

Se conoce por Comunicación entre procesos ó InterProcess Communication (IPC) al conjunto de mecanismos claves en la compartición de datos (intercomunicación) y sincronización entre distintos procesos. Los procesos que se ejecutan concurrentemente pueden ser independientes o cooperativos. Los procesos independientes cuando no pueden alterar o verse alterados por otros procesos que están en ejecución. En cambio, los procesos cooperativos pueden verse afectados y afectar a los demás procesos. Razones por las cuales proporciar entornos que permitan la cooperación entre procesos:

  • Compartir información: Ante una eventual necesidad que múltiples usuarios necesiten la misma información (Archivo compartido), se debe proveer un entorno que habilite el acceso concurrente a dicha información
  • Acelerar los cálculos: Al desear que una tarea se ejecute mas rápido, se divide en subtareas, implementando un paralelismo de ejecución entre si. Esto se consigue con con computadoras de multiples elementos de procesamiento, ya sea a nivel de cpu’s o canales de E/S.
  • Modularidad: Al querer construirse un sistema de forma modular, se necesita dividir la información del sistema en distintos procesos, o hebras.
  • Conveniencia: Ya sea para un solo usuario, puede éste querer trabajar en varias tareas simultáneamente. Por ejemplo usando editor de texto, escuchando música e imprimiendo al mismo tiempo.

Dentro de los mecanismos más usados, tenemos el paso por mensajes, la memoria compartida y los semáforos. El paso por mensajes se puede ver como una lista enlazada de mensajes dentro del espacio de direccionamiento del núcleo. Una aplicación, siempre que tenga los derechos necesarios, puede depositar un mensaje (de cualquier tipo) en ella, y otras aplicaciones podrán leerlo. Es posible asignar atributos a los mensajes, de forma que se puedan mantener ordenados por prioridad en lugar de por orden de llegada. Esta información se detallará más profundamente en la próxima sección.

La memoria compartida es un medio que permite establecer una zona común de memoria entre varias aplicaciones. Y los semáforos, que son una herramienta puramente de sincronización. Permiten controlar el acceso de varios procesos a recursos comunes.

Contenido

Memoria Compartida

El mecanismo de memoria compartida permite a dos o más procesos compartir un segmento de memoria, y por consiguiente, los datos que hay en él. Es por ello el método más rápido de comunicación entre procesos. Al ser el objetivo de este tipo de comunicación la transferencia de datos entre varios procesos, los programas que utilizan memoria compartida deben normalmente establecer algún tipo de protocolo para el bloqueo. Este protocolo puede ser la utilización de semáforos, que es a su vez otro tipo de comunicación (sincronización) entre procesos. La memoria que maneja un proceso, y también la compartida, va a ser virtual, por lo que su dirección física puede variar con el tiempo. Esto no va a plantear ningún problema, ya que los procesos no generan direcciones físicas, sino virtuales, y es el núcleo (con su gestor de memoria) el encargado de traducir unas a otras.

Utilización

Para aprovechar las ventajas que aporta el uso de memoria compartida se dispone de 4 llamadas al sistema: shmget(), shmctl(), shmat() y shmdt(). En este primer apartado se explicará de una forma general la utilidad de estas llamadas, para ser luego vistas con todo detalle en el siguiente apartado.

shmget()

Permite acceder a una zona de memoria compartida y, opcionalmente, crearla en caso de no existir. A esta llamada se le pasan tres argumentos: una clave, el tamaño del segmento a crear y el flag inicial de operación, y devuelve un entero, denominado shmid, que se utiliza para hacer referencia a dicho segmento.


   #include <sys/ipc.h>
   #include <sys/shm.h>
   int shmget(key_t key, size_t size, int shmflg);


Notar que shmget() únicamente reserva el espacio necesario para alojar el segmento. El segmento no se crea hasta que algún proceso se asigne a él. La posición de memoria final la decide, en principio, el sistema. Si se utiliza para obtener una referencia a una zona de memoria compartida ya existente, el tamaño especificado debe ser inferior o igual al de la memoria existente. En caso contrario, el tamaño asignado debe ser múltiplo de PAGE_SIZE, que corresponde al tamaño de una página de memoria (4 KB en la arquitectura x86). El valor de shmflg se compone básicamente con:

  • IPC_CREAT: Para crear un nuevo segmento. Si este flag no se precisa, shmget() únicamente buscará el segmento asociado con la clave y comprobará si el usuario tiene permisos para acceder a él.
  • IPC_EXCL: Se utiliza junto a IPC_CREAT para asegurar el fallo si el segmento existe.
  • mode_flags: Los 9 bits menos significativos del número están reservados para el establecimiento de permisos de acceso. Actualmente los permisos de ejecución no son utilizados por el sistema.

shmctl()

   #include <sys/ipc.h>
   #include <sys/shm.h>
   int shmctl (int shmid, int cmd, struct shmid_ds *buf);



Proporciona una variedad de operaciones para el control de la memoria compartida a través de cmd. Algunas de las operaciones disponibles son:

  • IPC_STAT: Lee el estado de la estructura de control de la memoria asociada a shmid y lo

devuelve a través de la estructura de datos apuntada por buf.

  • IPC_SET: Cambia el valor de los siguientes miembros de la estructura de datos asociada a

shmid con el correspondiente valor encontrado en la estructura apuntada por buf: shm_perm.uid shm_perm.gid shm_perm.mode

  • IPC_RMID: Marca una región de memoria compartida como destruida, aunque el borrado

sólo se hará efectivo cuando el último proceso que la adjuntaba deje de hacerlo. Si en el momento en que se realiza la invocación, el segmento aún está asignado a otro proceso, la clave será puesta a IPC_PRIVATE.

  • SHM_LOCK: Bloquea la zona de memoria compartida especificada por shmid. Esto quiere

decir que el segmento es grabado en memoria, no siendo posible borrarlo a partir de esta operación. Tampoco se podrá hacer swapping sobre él. Esta cmd solo puede ser ejecutada por un proceso que tenga un ID de usuario efectivo igual al del superusuario. De esta forma se garantiza la permanencia de los datos en la memoria.

  • SHM_UNLOCK: Desbloquea la región de memoria compartida especificada por shmid.

Esta operación, al igual que la anterior, sólo la podrán ejecutar aquellos procesos con privilegios de acceso apropiados.

shmat()

Es la llamada que debe invocar un proceso para adjuntar una zona de memoria compartida dentro de su espacio de direcciones. Recibe tres parámetros: el identificador del segmento (shmid), una dirección de memoria (shmaddr) y las banderas descritas más adelante. La dirección puede ser NULL; en tal caso el sistema operativo tomará la responsabilidad de buscar una posición de memoria libre. En option se puede especificar:

  • SHM_RND: En cuyo caso, el sistema intentará vincular la zona de memoria a una dirección

múltiplo de SHMLBA (shmparam.h) lo más próxima posible a la especificada.

  • SHM_RDONLY: Hará que el proceso sólo pueda acceder al segmento de memoria en

lectura. Si no se precisa, el segmento se vinculará en modo lectura/escritura.


   #include <sys/types.h>
   #include <sys/shm.h>
   void* shmat (int shmid, const void *shmaddr, int option);

Como resultado de la invocación, devuelve la dirección de comienzo del segmento de memoria asignado y se actualizan los siguientes campos de la estructura shmid_kernel: shm_atim, que recibe la fecha actual; shm_lprid, que recibe el pid del proceso que llama, y shm_nattch, que se incrementa en una unidad.

shmdt()

Es la operación que realizará el proceso anterior para desvincularse de una zona de memoria compartida. Para ello, deberá precisarse como primer y único parámetro la dirección shmaddr de dicha zona. Esta llamada al sistema actualiza los campos siguientes de las estructura shmid_kernel: shm_dtim, que recibe la fecha actual; shm_lprid, que recibe el pid del proceso que llama y shm_nattch, que queda decrementado en una unidad.

Semáforos

Un semáforo es un mecanismo de sincronización que se utiliza generalmente en sistemas con memoria compartida, bien sea un monoprocesador o un multiprocesador. Su uso en un multicomputador depende del sistema operativo en particular. Un semáforo es un objeto con un valor entero al que se le puede asignar un valor inicial no negativo y al que sólo se puede acceder utilizando dos operaciones atómicas: wait y signal (también llamadas down o up, respectivamente). Las definiciones de estas dos operaciones son las siguientes:


   wait(s){
     s = s - 1;
     if (s < 0)
       Bloquear al proceso;
   }
   signal(s){
     s = s + 1;
     if ( s <= 0)
       Desbloquear a un proceso bloqueado en la operación wait;
   }


El número de procesos que en un instante determinado se encuentran bloqueados en una operación wait viene dado por el valor absoluto del semáforo si es negativo. Cuando un proceso ejecuta la operación signal, el valor del semáforo se incrementa. En el caso de que haya algún proceso bloqueado en una operación wait anterior, se desbloqueará a un solo proceso. Las operaciones wait y signal son dos operaciones genéricas que deben particularizarse en cada sistema operativo. A continuación se presentan los servicios que ofrece el estándar POSIX para trabajar con semáforos. En POSIX, un semáforo se identifica mediante una variable del tipo sem_t. El estándar POSIX define dos tipos de semáforos:

  • Semáforos sin nombre: Permiten sincronizar a los procesos ligeros que ejecutan dentro de

un mismo proceso o a los procesos que lo heredan a través de la llamada fork.

  • Semáforos con nombre: En este caso, el semáforo lleva asociado un nombre que sigue la

convención de nombrado que se emplea para archivos. Con este tipo de semáforos se pueden sincronizar procesos sin necesidad de que tengan que heredar el semáforo utilizando la llamada fork.

Resumen

Estos modelos son bastante comunes, y han de usarse en los distintos sistemas operativos, muchos sistemas implementan ambos, el paso de mensajes es útil de implementar en el paso de pequeñas cantidades de información, resulta más fácil de implementar como mecanismo de comunicación entre computadoras. La implementación de memoria compartida resulta tener una velocidad máxima, ya que funciona a nivel de velocidad de memoria, siendo mas rápida que la implementación de paso por mensaje que cuando se implementa se hacen llamadas al sistema, donde se requiere la intervención del kernel el cual consume mas tiempo. En las implementaciones de memoria compartida las llamadas al sistema no se necesitan para establecer las zonas de memoria compartida. Una vez que se establecen las zonas de memorias compartidas, éstas se tratan como zonas de memoria rutinarias para los procesos intervenidos.

Herramientas personales
Espacios de nombres
Variantes
Acciones
Navegación
Herramientas