Zona de datos de memoria
La memoria compartida es uno de los mecanismos de Comunicación Entre Procesos (IPC) que hay en Linux.
Para usar memoria compartida en Linux es necesario seguir una serie de pasos que luego se traducen a llamadas al sistema.
- Necesitamos obtener un identificador de IPC. Para ello convertimos una ruta (path) del sistema en un identificador IPC. Este identificador es necesario para crear la crear la zona de memoria virtual. Esto es muy sencillo de hacer con la llamada al sistema ftok.
- Crear el segmento de memoria compartida con la llamada al sistema shmget.
- Operar con la memoria compartida. Indicamos lo que queremos compartir con la llamada al sistema shmat.
- Destruimos el segmento de memoria compartida con la llamada al sistema shmdt y shmctl.
Obtener el identificador IPC
Modo de uso:
#include <sys/types.h> #include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id);
El primer parámetro es una ruta. Lo que se puede hacer es coger una ruta que siempre esté en el sistema, por ejemplo "/bin/cp".
El segundo parámetro es un número aleatorio, pero que conozcan todos
los procesos que quieren unirse al mismo segmento de memoria compartida
(al igual que la ruta).
Por ejemplo podemos hacer:int key = ftok ("/bin/cp", 123);Información más detallada:
$ man ftok
Crear el segmento de memoria compartida
Esto lo hacemos con la llamada al sistema shmget.
#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg);
- El primer parámetro es la clave obtenida en la llamada al sistema anterior.
- El segundo parámetro es el tamaño de la memoria a compartir dados en bytes.
- El tercer parámetro son flags para el modo de uso y quién accede al segmento de memoria.
Los flags son:
- IPC_CREAT: crea un nuevo segmento.
- IPC_EXCL: se combina con IPC_CREAT y si el segmento ya existía, entonces la creación de segmento falla.
- mode_flags: son los permisos del segmento sobre usuario, grupo y otros, además de los permisos especiales.
Por ejemplo, creamos una zona de memoria compartida para 10 enteros
int id = shmget(key, sizeof(int) * 10, 0777 | IPC_CREAT);
Información más detallada:
$ man shmget
Operaciones con la memoria compartida
Ahora tenemos que unir nuestros datos
al segmento de memoria compartida. Esto es lo que hace la llamada al
sistema shmat. Se le especifica el ID obtenido en shmget:
void *shmat(int shmid, const void *shmaddr, int shmflg);
La dirección de memoria compartida a
la que se asocia depende del parámetro shmaddr y shmflg. Para más
información sobre estos dos parámetros hacer un man shmat.
Para el uso que le vamos a dar, bastará con poner estos dos parámetros a 0, con esto le indicamos que el sistema coja una dirección apropiada donde fijar el segmento.
int *array; array = shmat(id, 0, 0);
Desasignar la memoria compartida
Cuando ya hayamos acabado de
usar la memoria compartida, se debe liberar el segmento "cogido". Esto
se hace con 2 llamadas al sistema: shmdt y shmctl.
- shmdt: lo que hace es que desasocia la zona de datos del programa con la memoria compartida.
- shmctl: sirve para pasar recibir información de la memoria compartida, o para establecer usuario y permisos del segmento. También sirve para destruir el segmento de memoria compartida.
/* Free the shared memory */ shmdt ((char *)array); shmctl (id, IPC_RMID, (struct shmid_ds *)NULL);
El parámetro IPC_RMID lo que hace es eliminar el segmento de memoria compartida.
Ejemplo
Se tienen 2 programas. Uno cliente y otro servidor (si se quiere ver así). El servidor crea la memoria compartida y sirve un dato. El cliente se acopla a la memoria compartida y recoge el dato.
/* p1.c -- demostrate the mecanism of * shared memory * blog : snatverk.blogspot.com * date : Tue Sep 14 10:54:37 WEST 2010 * compile: $ gcc p1.c -o p1 */ #include <stdio.h> #include <sys/types.h>
#include <sys/ipc.h> #include <string.h> #include <errno.h> #include <sys/shm.h> /* shm* */ #define FILEKEY "/bin/cat" #define KEY 1300 #define MAXBUF 10 int main () { /* Key to shared memory */ int key = ftok(FILEKEY, KEY); if (key == -1) { fprintf (stderr, "Error with key \n"); return -1; }
/* we create the shared memory */ int id_zone = shmget (key, sizeof(int)*MAXBUF, 0777 | IPC_CREAT); if (id_zone == -1) { fprintf (stderr, "Error with id_zone \n"); return -1; }
printf ("ID zone shared memory: %i\n", id_zone);
int *buffer; /* shared buffer */ /* we declared to zone to share */ buffer = shmat (id_zone, (char *)0, 0); if (buffer == NULL) { fprintf (stderr, "Error reserve shared memory \n"); return -1; }
printf ("Pointer buffer shared memory: %p\n", buffer);
int i; for (i = 0; i < MAXBUF; i++) buffer[i] = i;
/* The daemon executes until press some character */ char c; c = getchar();
/* Free the shared memory */ shmdt ((char *)buffer); shmctl (id_zone, IPC_RMID, (struct shmid_ds *)NULL); return 0; }
___________________________________________________
El segundo proceso:
/* p2.c -- demostrate the mecanism of * shared memory * blog : snatverk.blogspot.com * compile: $ gcc p2.c -o p2 */ #include <stdio.h> #include <sys/types.h>
#include <sys/ipc.h> #include <string.h> #include <errno.h> #include <sys/shm.h> /* shm* */ #define FILEKEY "/bin/cat" #define KEY 1300 #define MAXBUF 10 int main () { /* Key to shared memory */ int key = ftok(FILEKEY, KEY); if (key == -1) {
fprintf (stderr, "Error with key \n"); return -1; } /* we create the shared memory */ int id_zone = shmget (key, sizeof(int)*MAXBUF, 0777 | IPC_CREAT); if (id_zone == -1) { fprintf (stderr, "Error with id_zone \n"); return -1; } printf ("ID zone shared memory: %i\n", id_zone); int *buffer; /* shared buffer */ /* we declared to zone to share */ buffer = shmat (id_zone, (char *)0, 0); if (buffer == NULL) {
fprintf (stderr, "Error reserve shared memory \n"); return -1; }
printf ("Pointer buffer shared memory: %p\n", buffer); /* Write the values of shared memory */ int i; for (i = 0; i < MAXBUF; i++) printf ("%i\n", buffer[i]); return 0; }
0 comentarios:
Publicar un comentario