in

Memoria compartida

shared memory

La memoria compartida es una memoria compartida entre dos o más procesos. Sin embargo, ¿por qué necesitamos compartir la memoria o algún otro medio de comunicación?

Para reiterar, cada proceso tiene su propio espacio de direcciones, si algún proceso quiere comunicarse con alguna información de su propio espacio de direcciones a otros procesos, entonces solo es posible con técnicas de IPC (comunicación entre procesos). Como ya sabemos, la comunicación puede ser entre procesos relacionados o no relacionados.

Por lo general, la comunicación de procesos interrelacionados se realiza mediante tuberías o tuberías con nombre. La comunicación de procesos no relacionados (por ejemplo, un proceso que se ejecuta en un terminal y otro proceso en otro terminal) se puede realizar mediante canalizaciones con nombre o mediante técnicas populares de IPC de memoria compartida y colas de mensajes.

Hemos visto las técnicas de IPC de tuberías y tuberías con nombre y ahora es el momento de conocer las técnicas de IPC restantes, a saber, memoria compartida, colas de mensajes, semáforos, señales y mapeo de memoria.

En este capítulo, lo sabremos todo sobre la memoria compartida.

Memoria compartida

Sabemos que para comunicarnos entre dos o más procesos, usamos la memoria compartida, pero antes de usar la memoria compartida, lo que hay que hacer con las llamadas al sistema, veamos esto:

  • Cree el segmento de memoria compartida o use un segmento de memoria compartida ya creado (shmget ())

  • Adjunte el proceso al segmento de memoria compartida ya creado (shmat ())

  • Separar el proceso del segmento de memoria compartida ya adjunto (shmdt ())

  • Operaciones de control en el segmento de memoria compartida (shmctl ())

Veamos algunos detalles de las llamadas al sistema relacionadas con la memoria compartida.

#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg)

La llamada al sistema anterior crea o asigna un segmento de memoria compartida de System V. Los argumentos que deben pasarse son los siguientes:

los primer argumento, clave, reconoce el segmento de memoria compartida. La clave puede ser un valor arbitrario o uno que se pueda derivar de la función de biblioteca ftok (). La clave también puede ser IPC_PRIVATE, es decir, ejecutar procesos como servidor y cliente (relación padre e hijo), es decir, comunicación de procesos interrelacionados. Si el cliente desea utilizar la memoria compartida con esta clave, entonces debe ser un proceso hijo del servidor. Además, el proceso hijo debe crearse después de que el padre haya obtenido una memoria compartida.

los segundo argumento, tamaño, es el tamaño del segmento de memoria compartida redondeado a un múltiplo de PAGE_SIZE.

los tercer argumento, shmflg, especifica los indicadores de memoria compartida necesarios, como IPC_CREAT (creación de un nuevo segmento) o IPC_EXCL (se utiliza con IPC_CREAT para crear un nuevo segmento y la llamada falla, si el segmento ya existe). También es necesario aprobar los permisos.

Nota – Consulte las secciones anteriores para obtener detalles sobre los permisos.

Esta llamada devolvería un identificador de memoria compartida válido (utilizado para más llamadas de memoria compartida) en caso de éxito y -1 en caso de error. Para conocer la causa de la falla, verifique con la variable errno o la función perror ().

#include <sys/types.h>
#include <sys/shm.h>

void * shmat(int shmid, const void *shmaddr, int shmflg)

La llamada al sistema anterior realiza una operación de memoria compartida para el segmento de memoria compartida del Sistema V, es decir, adjunta un segmento de memoria compartida al espacio de direcciones del proceso de llamada. Los argumentos que deben pasarse son los siguientes:

El primer argumento, shmid, es el identificador del segmento de memoria compartida. Este id es el identificador de memoria compartida, que es el valor de retorno de la llamada al sistema shmget ().

El segundo argumento, shmaddr, es especificar la dirección adjunta. Si shmaddr es NULL, el sistema elige por defecto la dirección adecuada para adjuntar el segmento. Si shmaddr no es NULL y SHM_RND se especifica en shmflg, el adjunto es igual a la dirección del múltiplo más cercano de SHMLBA (Dirección de límite inferior). De lo contrario, shmaddr debe ser una dirección alineada con la página en la que se produce / inicia el adjunto de memoria compartida.

El tercer argumento, shmflg, especifica los indicadores de memoria compartida requeridos, como SHM_RND (dirección de redondeo a SHMLBA) o SHM_EXEC (permite que se ejecute el contenido del segmento) o SHM_RDONLY (adjunta el segmento con fines de solo lectura, por defecto es de lectura y escritura) o SHM_REMAP (reemplaza el mapeo existente en el rango especificado por shmaddr y continúa hasta el final del segmento).

Esta llamada devolvería la dirección del segmento de memoria compartida adjunta en caso de éxito y -1 en caso de falla. Para conocer la causa de la falla, verifique con la variable errno o la función perror ().

#include <sys/types.h>
#include <sys/shm.h>

int shmdt(const void *shmaddr)

La llamada al sistema anterior realiza una operación de memoria compartida para el segmento de memoria compartida del Sistema V de separar el segmento de memoria compartida del espacio de direcciones del proceso de llamada. El argumento que debe pasarse es:

El argumento, shmaddr, es la dirección del segmento de memoria compartida que se va a separar. El segmento que se va a separar debe ser la dirección devuelta por la llamada al sistema shmat ().

Esta llamada devolvería 0 en caso de éxito y -1 en caso de error. Para conocer la causa de la falla, verifique con la variable errno o la función perror ().

#include <sys/ipc.h>
#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

La llamada al sistema anterior realiza una operación de control para un segmento de memoria compartida del Sistema V. Deben pasarse los siguientes argumentos:

El primer argumento, shmid, es el identificador del segmento de memoria compartida. Este id es el identificador de memoria compartida, que es el valor de retorno de la llamada al sistema shmget ().

El segundo argumento, cmd, es el comando para realizar la operación de control requerida en el segmento de memoria compartida.

Los valores válidos para cmd son:

  • IPC_STAT – Copia la información de los valores actuales de cada miembro de la estructura shmid_ds a la estructura pasada señalada por buf. Este comando requiere permiso de lectura para el segmento de memoria compartida.

  • IPC_SET – Establece el ID de usuario, el ID de grupo del propietario, los permisos, etc. señalados por la estructura buf.

  • IPC_RMID – Marca el segmento a destruir. El segmento se destruye solo después de que el último proceso lo haya separado.

  • IPC_INFO – Devuelve la información sobre los límites y parámetros de la memoria compartida en la estructura apuntada por buf.

  • SHM_INFO – Devuelve una estructura shm_info que contiene información sobre los recursos del sistema consumidos por la memoria compartida.

El tercer argumento, buf, es un puntero a la estructura de memoria compartida llamada struct shmid_ds. Los valores de esta estructura se usarían para set o get según cmd.

Esta llamada devuelve el valor según el comando pasado. Tras el éxito de IPC_INFO y SHM_INFO o SHM_STAT devuelve el índice o identificador del segmento de memoria compartida o 0 para otras operaciones y -1 en caso de falla. Para conocer la causa de la falla, verifique con la variable errno o la función perror ().

Consideremos el siguiente programa de muestra.

  • Cree dos procesos, uno es para escribir en la memoria compartida (shm_write.c) y otro es para leer desde la memoria compartida (shm_read.c)

  • El programa realiza la escritura en la memoria compartida mediante el proceso de escritura (shm_write.c) y la lectura de la memoria compartida mediante el proceso de lectura (shm_read.c)

  • En la memoria compartida, el proceso de escritura crea una memoria compartida de tamaño 1K (y banderas) y adjunta la memoria compartida

  • El proceso de escritura escribe 5 veces los alfabetos de ‘A’ a ‘E’ cada uno de 1023 bytes en la memoria compartida. El último byte significa el final del búfer

  • El proceso de lectura leería de la memoria compartida y escribiría en la salida estándar

  • Las acciones del proceso de lectura y escritura se realizan simultáneamente

  • Después de completar la escritura, el proceso de escritura se actualiza para indicar la finalización de la escritura en la memoria compartida (con la variable completa en la estructura shmseg)

  • El proceso de lectura realiza la lectura desde la memoria compartida y se muestra en la salida hasta que obtiene una indicación de la finalización del proceso de escritura (variable completa en struct shmseg)

  • Realiza el proceso de lectura y escritura unas cuantas veces para simplificar y también para evitar bucles infinitos y complicar el programa.

A continuación se muestra el código para el proceso de escritura (Escritura en memoria compartida – Archivo: shm_write.c)

/* Filename: shm_write.c */
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>

#define BUF_SIZE 1024
#define SHM_KEY 0x1234

struct shmseg {
   int cnt;
   int complete;
   char buf[BUF_SIZE];
};
int fill_buffer(char * bufptr, int size);

int main(int argc, char *argv[]) {
   int shmid, numtimes;
   struct shmseg *shmp;
   char *bufptr;
   int spaceavailable;
   shmid = shmget(SHM_KEY, sizeof(struct shmseg), 0644|IPC_CREAT);
   if (shmid == -1) {
      perror("Shared memory");
      return 1;
   }
   
   // Attach to the segment to get a pointer to it.
   shmp = shmat(shmid, NULL, 0);
   if (shmp == (void *) -1) {
      perror("Shared memory attach");
      return 1;
   }
   
   /* Transfer blocks of data from buffer to shared memory */
   bufptr = shmp->buf;
   spaceavailable = BUF_SIZE;
   for (numtimes = 0; numtimes < 5; numtimes++) {
      shmp->cnt = fill_buffer(bufptr, spaceavailable);
      shmp->complete = 0;
      printf("Writing Process: Shared Memory Write: Wrote %d bytesn", shmp->cnt);
      bufptr = shmp->buf;
      spaceavailable = BUF_SIZE;
      sleep(3);
   }
   printf("Writing Process: Wrote %d timesn", numtimes);
   shmp->complete = 1;

   if (shmdt(shmp) == -1) {
      perror("shmdt");
      return 1;
   }

   if (shmctl(shmid, IPC_RMID, 0) == -1) {
      perror("shmctl");
      return 1;
   }
   printf("Writing Process: Completen");
   return 0;
}

int fill_buffer(char * bufptr, int size) {
   static char ch="A";
   int filled_count;
   
   //printf("size is %dn", size);
   memset(bufptr, ch, size - 1);
   bufptr[size-1] = '';
   if (ch > 122)
   ch = 65;
   if ( (ch >= 65) && (ch <= 122) ) {
      if ( (ch >= 91) && (ch <= 96) ) {
         ch = 65;
      }
   }
   filled_count = strlen(bufptr);
   
   //printf("buffer count is: %dn", filled_count);
   //printf("buffer filled is:%sn", bufptr);
   ch++;
   return filled_count;
}

Pasos de compilación y ejecución

Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Shared Memory Write: Wrote 1023 bytes
Writing Process: Wrote 5 times
Writing Process: Complete

A continuación se muestra el código para el proceso de lectura (lectura de la memoria compartida y escritura en la salida estándar – Archivo: shm_read.c)

/* Filename: shm_read.c */
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>

#define BUF_SIZE 1024
#define SHM_KEY 0x1234

struct shmseg {
   int cnt;
   int complete;
   char buf[BUF_SIZE];
};

int main(int argc, char *argv[]) {
   int shmid;
   struct shmseg *shmp;
   shmid = shmget(SHM_KEY, sizeof(struct shmseg), 0644|IPC_CREAT);
   if (shmid == -1) {
      perror("Shared memory");
      return 1;
   }
   
   // Attach to the segment to get a pointer to it.
   shmp = shmat(shmid, NULL, 0);
   if (shmp == (void *) -1) {
      perror("Shared memory attach");
      return 1;
   }
   
   /* Transfer blocks of data from shared memory to stdout*/
   while (shmp->complete != 1) {
      printf("segment contains : n"%s"n", shmp->buf);
      if (shmp->cnt == -1) {
         perror("read");
         return 1;
      }
      printf("Reading Process: Shared Memory: Read %d...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

MediaHuman Video Converter convertir video

Konvertieren Sie Videos en un formato de creencias con MediaHuman Video Converter

apple touch icon@2

¿Superíndice en rebajas (con sabor a Github)?