2009-11-04 20 views
6

Sto tentando di scrivere un programma in cui i processi figli comunicano tra loro su Linux.Come si mantiene un int e un array nella memoria condivisa in C?

Questi processi sono tutti creati dallo stesso programma e come tali condividono il codice.

Ho bisogno che abbiano accesso a due variabili integer e a un array intero.

Non ho idea di come funzioni la memoria condivisa e ogni risorsa che ho cercato non abbia fatto altro che confondermi.

Qualsiasi aiuto sarebbe molto apprezzato!

Modifica: Ecco un esempio di codice che ho scritto finora solo per condividere un int ma probabilmente è sbagliato.

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

Quale sistema operativo? –

+1

Il mio errore. Questo è su Linux – Josh

+0

Nota questa domanda di ieri: http://stackoverflow.com/questions/1664519/creating-accessing-shared-memory-in-c (stesso argomento generale, sebbene sia stato selezionato Sys V IPC). –

risposta

6

È necessario aumentare la dimensione della memoria condivisa. Quanto è grande un array di cui hai bisogno? Qualunque sia il valore, è necessario selezionarlo prima di creare il segmento di memoria condivisa - la memoria dinamica non funzionerà troppo bene qui.

Quando si collega alla memoria condivisa, si ottiene un puntatore all'indirizzo iniziale. Sarà sufficientemente ben allineato per essere utilizzato per qualsiasi scopo. Quindi, è possibile creare puntatori ai due variabili e serie in questo senso (cribbing alcuni dello scheletro dal tuo esempio di codice) - Si noti l'uso di puntatori per accedere alla memoria condivisa:

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

Sembra molto bello. Grazie mille! – Josh

0

Questa guida sembra utile: http://www.cs.cf.ac.uk/Dave/C/node27.html. Include alcuni programmi di esempio.

Ci sono anche Linux man pages online.

+0

Grazie, ma sfortunatamente è una di quelle pagine che mi ha completamente confuso. – Josh

+0

Hai provato a copiare e incollare il codice di esempio lì e compilarlo? Se riesci a farlo compilare probabilmente sei a metà strada per comprenderlo. –

+0

Il mio problema con quell'esempio è che sembra che ci siano diversi programmi che parlano in modo client-server. Non avevo ancora chiarito cosa mi serviva in quel momento nella mia domanda iniziale, ma nel mio codice creerò più processi dallo stesso programma e ne avremo bisogno per comunicare. – Josh

0

La memoria condivisa è solo un segmento di memoria assegnato da un processo, con un ID univoco, e l'altro processo farà anche l'allocazione, con lo stesso id, e la dimensione della memoria è la dimensione della struttura che stanno usando, quindi avresti una struttura con 2 numeri interi e un array intero.

Ora entrambi hanno un puntatore alla stessa memoria, quindi le scritture di una sovrascriveranno qualsiasi altra cosa c'era e l'altra avrà accesso immediato ad essa.

+0

@Josh no, la formattazione dei commenti fa schifo rocce - ma poi dovresti modificare la tua domanda per chiarirla, invece di commentare, in modo da poter formattare il tuo codice in una modifica della tua risposta ed eliminare questi commenti! –

+0

Ti consiglierei di aggiungere un chiarimento alla tua domanda originale. –

+0

@Josh - puoi dare un'occhiata a questo tutorial: http://www.ecst.csuchico.edu/~beej/guide/ipc/shmem.html, come mostra anche come usare ftok per creare una chiave per chiamata. –

0

Dal tuo commento sembra che tu stia usando IPC_PRIVATE, e che sicuramente sembra sbagliato (i tipi "privati" suggeriscono che non è pensato per la condivisione, no? -). Prova qualcosa del tipo:

#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

Sembra interessante. Non sono il massimo quando si tratta di C, quindi in questo caso sarà l'array int? Sono anche curioso del valore esadecimale che hai nel shmget. – Josh

+0

IPC_PRIVATE funziona se il genitore crea la memoria condivisa e quindi avvia i bambini che stanno per condividerli. –

+0

@Josh: è necessario un valore a 32 bit come chiave per la memoria condivisa. Puoi usare ftok() per crearne uno o scegliere un nome fisso. No Bad Dood è un buon nome come qualsiasi altro per un pezzo di memoria condivisa come qualsiasi altro. 0xDEADBEEF è un altro valore ben noto. Ma IPC_PRIVATE è buono anche se il processo genitore crea e allega la memoria condivisa prima della foratura. –

Problemi correlati