2009-11-04 36 views
6

Estoy intentando escribir un programa en el que los procesos secundarios se comunican entre sí en Linux.¿Cómo se puede mantener un int y una matriz en la memoria compartida en C?

Todos estos procesos se crean a partir del mismo programa y, como tal, comparten el código.

Necesito que tengan acceso a dos variables enteras, así como a una matriz entera.

No tengo idea de cómo funciona la memoria compartida y cada recurso que he buscado no ha hecho más que confundirme.

¡Cualquier ayuda sería muy apreciada!

Editar: Aquí hay un ejemplo de código que he escrito hasta ahora solo para compartir un int pero probablemente sea incorrecto.

int segmentId; 
int sharedInt; 
const int shareSize = sizeof(int); 
/* Allocate shared memory segment */ 
segmentId = shmget(IPC_PRIVATE, shareSize, S_IRUSR | S_IWUSR); 

/* attach the shared memory segment */  
sharedInt = (int) shmat(segmentId, NULL, 0); 

/* Rest of code will go here */ 

/* detach shared memory segment */ 
shmdt(sharedInt); 
/* remove shared memory segment */ 
shmctl(segmentId, IPC_RMID, NULL); 
+4

Qué sistema operativo? –

+1

Mi error. Esto está en Linux – Josh

+0

Tenga en cuenta esta pregunta de ayer: http://stackoverflow.com/questions/1664519/creating-accessing-shared-memory-in-c (el mismo tema general, aunque ha seleccionado Sys V IPC). –

Respuesta

6

Necesitará aumentar el tamaño de su memoria compartida. ¿Qué tan grande es el conjunto que necesitas? Sea cual sea el valor, tendrá que seleccionarlo antes de crear el segmento de memoria compartida; la memoria dinámica no funcionará demasiado bien aquí.

Cuando se conecta a la memoria compartida, se obtiene un puntero a la dirección de inicio. Estará lo suficientemente alineado para ser usado para cualquier propósito. Por lo tanto, puede crear punteros a sus dos variables y variedad a lo largo de estas líneas (apuntalamiento algunos del esqueleto de su ejemplo de código) - nota el uso de punteros para acceder a la memoria compartida:

enum { ARRAY_SIZE = 1024 * 1024 }; 
int segmentId; 
int *sharedInt1; 
int *sharedInt2; 
int *sharedArry; 

const int shareSize = sizeof(int) * (2 + ARRAY_SIZE); 
/* Allocate shared memory segment */ 
segmentId = shmget(IPC_PRIVATE, shareSize, S_IRUSR | S_IWUSR); 

/* attach the shared memory segment */  
sharedInt1 = (int *) shmat(segmentId, NULL, 0); 
sharedInt2 = sharedInt1 + 1; 
sharedArry = sharedInt1 + 2; 

/* Rest of code will go here */ 
...fork your child processes... 
...the children can use the three pointers to shared memory... 
...worry about synchronization... 
...you may need to use semaphores too - but they *are* complex... 
...Note that pthreads and mutexes are no help with independent processes... 

/* detach shared memory segment */ 
shmdt(sharedInt1); 
/* remove shared memory segment */ 
shmctl(segmentId, IPC_RMID, NULL); 
+0

Esto se ve muy bien. ¡Muchas gracias! – Josh

0

Esta guía es útil: http://www.cs.cf.ac.uk/Dave/C/node27.html. Incluye algunos programas de ejemplo.

También hay Linux man pages online.

+0

Gracias, pero lamentablemente esa es una de esas páginas que me confundieron por completo. – Josh

+0

¿Has intentado copiar y pegar el código de ejemplo allí y compilarlo? Si puede compilar eso, probablemente esté a medio camino de entenderlo. –

+0

Mi problema con ese ejemplo es que parece que hay diferentes programas que hablan de manera cliente-servidor. No había aclarado lo que necesitaba en ese momento en mi pregunta original, pero en mi código crearé múltiples procesos del mismo programa y los necesitaré para comunicarme. – Josh

0

La memoria compartida es solo un segmento de memoria asignado por un proceso, con una identificación única, y el otro proceso también hará la asignación, con la misma identificación, y el tamaño de la memoria es el tamaño de la estructura que usted están usando, por lo que tendría una estructura con 2 enteros y una matriz entera.

Ahora ambos tienen un puntero a la misma memoria, por lo que las escrituras de una sobrescribirán cualquier otra cosa que haya, y la otra tiene acceso inmediato a ella.

+0

@Josh no, el formateo de comentarios apesta a rocas mohosas, pero se supone que debes editar tu pregunta para aclararla, en lugar de comentar, para que puedas formatear tu código bellamente en una edición de tu respuesta y eliminar estos comentarios. –

+0

Le recomiendo que agregue una aclaración a su pregunta original. –

+0

@Josh - es posible que desee consultar este tutorial: http://www.ecst.csuchico.edu/~beej/guide/ipc/shmem.html, ya que también muestra cómo usar ftok para crear una clave para el llamada. –

0

De tu comentario parece que estás usando IPC_PRIVATE, y eso definitivamente se ve mal (los tipos "privados" sugieren que no es para compartir, ¿no? -). Pruebe algo como:

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

... 

int segid = shmget((key_t)0x0BADDOOD, shareSize, IPC_CREAT); 
if (segid < 0) { /* insert error processing here! */ } 
int *p = (int*) shmat(segid, 0, 0); 
if (!p) { /* insert error processing here! */ } 
+0

Eso se ve interesante. No soy el mejor en lo que respecta a C, por lo que p será la matriz int en este caso? También siento curiosidad por el valor hexadecimal que tienes en el shmget. – Josh

+0

IPC_PRIVATE funciona si el padre crea la memoria compartida y luego bifurca a los niños que van a compartirla. –

+0

@Josh: necesita un valor de 32 bits como clave para la memoria compartida. Puede usar ftok() para crear uno o elegir un nombre fijo. No Bad Dood es tan buen nombre como cualquier otro para compartir un recuerdo. 0xDEADBEEF es otro valor bien conocido. Pero IPC_PRIVATE también es bueno, siempre que el proceso principal cree y adjunte la memoria compartida antes de bifurcar. –

Cuestiones relacionadas