2.3.1 Memoria compartida

La memoria compartida es un medio que permite establecer una zona común de memoria entre varias aplicaciones.


La memoria convencional que puede direccionar un proceso a través de su espacio de direcciones virtuales es local a ese proceso, cualquier intento de direccionar esa memoria desde otro proceso va a provocar una violación de segmento.


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.


Por lo que la memoria compartida administra los procesos a realizar es muy importante en la gestión de memoria principal y de archivos, la cual se centra en optimizar la ejecución de trabajos sin intervención del usuario. La gestión de memoria implica cargar y descargar programas eficientemente para maximizar la utilización de recursos.


En cuanto a la gestión de archivos, asegura que los datos necesarios estén disponibles para los programas en lotes. La planificación cuidadosa de recursos garantiza que múltiples trabajos se ejecuten de manera eficiente, optimizando el rendimiento del sistema.


A continuación se presentan algunas de las funciones más utilizadas en el estándar POSIX para la implementación de memoria compartida en lenguaje C.

  1. shmget(): Obtiene o crea un segmento de memoria compartida. Permite a los procesos compartir información almacenada en un área de memoria compartida.
  2. shmctl(): Controla las propiedades de un segmento de memoria compartida, como la eliminación o modificación de permisos. Proporciona funciones de control sobre los segmentos de memoria compartida.
  3. shmat(): Asocia un segmento de memoria compartida al espacio de direcciones de un proceso. Permite que un proceso acceda y trabaje con el contenido de un segmento de memoria compartida.
  4. shmdt(): Desasocia un segmento de memoria compartida del espacio de direcciones de un proceso. Indica que un proceso ya no utilizará el segmento de memoria compartida.

Error al cargar imagen figura_10.png

Figura 10. Memoria.

  //Ejemplo 1:
            
  //El ejemplo siguiente es un programa en c que tiene dos procesos: un padre y un hijo con tuberías donde se ejemplifica correctamente las 
  //tuberías con memoria compartida.
            
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <sys /shm.h>
            
  int main() {
      int fd[2];                                                // Descriptores de archivo para la tubería
      pid_t pid;                                                // ID del proceso
      char *shared_memory;                                      // Puntero a la memoria compartida
      int shmid;                                                // ID de la memoria compartida
      char message[] = "Hola, mundo!";                          // Mensaje a transmitir

      // Crear la tubería
      if (pipe(fd) == -1) {
          perror("pipe");                                       // Imprimir error si falla la creación de la tubería
          exit(EXIT_FAILURE);
      }

      
      shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666);       // Crear la memoria compartida
      if (shmid < 0) {
          perror("shmget");                                      // Imprimir error si falla la creación de la memoria compartida
          exit(EXIT_FAILURE);
      }

      
      pid = fork();                                              // Crear el proceso hijo
      if (pid < 0) {
          perror("fork");                                        // Imprimir error si falla la creación del proceso hijo
          exit(EXIT_FAILURE);
      }

      if (pid > 0) {                                            // Proceso padre
          close(fd[0]);                                         // Cerrar el extremo de lectura de la tubería

          
          write(fd[1], message, sizeof(message) + 1);           // Escribir el mensaje en la tubería
          close(fd[1]);

          
          wait(NULL);                                           // Esperar a que el hijo termine

          
          shared_memory = shmat(shmid, NULL, 0);                // Leer el mensaje de la memoria compartida
          printf("Mensaje recibido: %s\n", shared_memory);

      } else {                                                // Proceso hijo
          close(fd[1]);                                       // Cerrar el extremo de escritura de la tubería

          
          read(fd[0], message, sizeof(message));              // Leer el mensaje de la tubería
          close(fd[0]);

          
          shared_memory = shmat(shmid, NULL, 0);              // Escribir el mensaje en la memoria compartida
          sprintf(shared_memory, "%s", message);
      }

      return 0;
  }
          
          

Código 6. Tuberías con memoria compartida.

Reflexiona la siguiente pregunta que será tratada en la sesión de clase.

¿Qué funciones desconoces del código 6 mostrado anteriormente?