2013-02-26 17 views
6

Ho due processi (client e server) che comunicano attraverso la memoria condivisa.C - Array dinamico 2D (Doppio puntatore) - Memoria condivisa

Devo creare una matrice 2D dinamica (basata su parametri). La matrice viene archiviata in una struct e quindi scritta nel segmento condiviso.

Posso scrivere la matrice nella memoria condivisa, ma non posso recuperarla dall'altra procedura.

Codice Cliente:

struct shared_use_st { 
    int  written_by_you; 
    int  **PID_PRI_array; 
}; 
      /* Prepare Dynamic 2D array */ 
     data_store = malloc(/*ROWS*/ 5 * sizeof(int*)); 
     for(i=0;i<5; i++) 
      data_store[i] = malloc(/*COLS*/ 2 * sizeof(int)); 


     /* Prepare Dynamic 2D array - Shared Memory Seg */ 
     shared_stuff->PID_PRI_array = malloc(/*ROWS*/ 5 * sizeof(int*)); 
     for(i=0;i<5; i++) 
      shared_stuff->PID_PRI_array[i] = malloc(/*COLS*/ 2 * sizeof(int)); 


     /* Write PID and PRI to data_store array */ 
     data_store[0][0] = pid; 
     data_store[0][1] = 1; 

     data_store[1][0] = 12345; 
     data_store[1][1] = 2; 

     data_store[2][0] = 12346; 
     data_store[2][1] = 3; 

     data_store[3][0] = 12347; 
     data_store[3][1] = 4; 

     data_store[4][0] = 12348; 
     data_store[4][1] = 5; 

      for(i=0;i<5;i++){ 
       for(x=0;x<=1;x++){ 
        shared_stuff->PID_PRI_array[i][x] = data_store[i][x]; 
       } 
      } 

Codice Server:

for(i=0;i<5;i++){ 
    printf("PID: %d, PRI:%d\n", shared_stuff->PID_PRI_array[i][0], shared_stuff->PID_PRI_array[i][1]);    
} 

ricevo un errore "Segmentation Fault".

Grazie.

+1

L'indirizzo di memoria condivisa è uguale in entrambi i processi? Se non lo è, i puntatori non funzioneranno. –

+0

Sì, sono gli stessi :) –

risposta

5

Anche se l'oggetto shared_stuff è nella memoria condivisa, non si sta scrivendo l'array nella memoria condivisa. Si sta allocando lo spazio con malloc, scrivendo i dati in quello spazio e quindi mettendo i puntatori a quello spazio in shared_stuff. malloc alloca lo spazio all'interno dello spazio di indirizzi normale del processo corrente, non in un segmento di memoria condivisa che è stato creato. È necessario scrivere i contenuti dell'array nella memoria condivisa.

Presumendo che ci sia spazio sufficiente per l'array all'interno del segmento di memoria condivisa, sarà necessario gestire gli indirizzi da soli, non utilizzando malloc. (Se lo spazio non è sufficiente, è necessario ampliare il segmento di memoria condivisa o trasmettere le informazioni in pezzi.)

È possibile posizionare un array a lunghezza variabile all'interno del segmento di memoria condivisa come segue.

In primo luogo, definire una struttura che contiene tutte le informazioni “gestione” è necessario, come ad esempio le dimensioni di matrice:

struct StuffStruct 
{ 
    size_t NumberOfRows, NumberOfColumns; 
    … Other information as desired. 
}; 

Creare un puntatore a quella struttura e impostarlo per puntare al segmento di memoria condivisa:

struct StuffStruct *Stuff = shm; // shm contains the address from shmat, performed previously. 

Creare un puntatore a una matrice con il numero desiderato di colonne e impostarlo al punto nel segmento di memoria condivisa dopo la struttura iniziale:

int (*data_store)[NumberOfColumns] = (int (*)[NumberOfColumns]) ((char *) Stuff + sizeof *Stuff); 

(Nota per puristi C: Sì, lo standard C non garantisce ciò che accade quando si esegue l'aritmetica del puntatore in questo modo. Tuttavia, qualsiasi implementazione fornendo supporto della memoria condivisa deve fornire il supporto per questo tipo di puntatori.)

noti che sizeof *Stuff + NumberOfRows * NumberOfColumns * size(int)deve essere maggiore della dimensione del segmento della memoria condivisa. Altrimenti supererai il segmento di memoria condivisa nel passaggio successivo.

Per il passaggio successivo, riempire l'array con i dati: Assegnare valori agli elementi di data_store come per un normale array bidimensionale.

Nel server, impostare Stuff allo stesso modo. Quindi, dopo che il client ha scritto il segmento di memoria condivisa, leggere i numeri di righe e colonne da Stuff. Quindi impostare data_store allo stesso modo.Quindi leggi da data_store.

+0

Scusa, ho dimenticato di dire che ho questo sopra; 'shared_stuff = (struct shared_use_st *) shm;' Dove SHM è il risultato di shmat;
\t '/ * attatch segmento per spazio per i dati */ \t if ((SHM = shmat (shmid, NULL, 0)) == (char *) - 1) \t { \t \t perror ("shmat"); \t \t _Esci (1); \t} \t printf ("[+] Segmento Attatched \ n"); ' Ho scritto questo pezzo di codice di prova nel client e restituisce esattamente ciò che mi aspetto; 'printf (" TEST \ n \ n "); per (i = 0; i <5; i ++) printf ("PID:% d, PRI:% d \ n", shared_stuff-> PID_PRI_array [i] [0], shared_stuff-> PID_PRI_array [i] [1] ]); \t ' –

+0

Il tuo commento è coerente con la mia diagnosi. Il codice nel client stampa ciò che ci si aspetta perché i dati si trovano nelle posizioni previste nello spazio degli indirizzi del client. Tuttavia, i dati non sono visibili nello spazio degli indirizzi del server. Solo la struttura puntata direttamente da 'shared_stuff' si trova nel segmento condiviso, perché hai impostato' shared_stuff' per puntare al segmento condiviso. I puntatori all'interno di quella struttura puntano a luoghi al di fuori del segmento condiviso, posti assegnati da 'malloc'. Poiché questi luoghi sono al di fuori del segmento condiviso, non sono visibili nel processo del server. –

+0

Vedo. Se lo faccio; 'shared_stuff-> written_by_you = 1;' questo è visibile dal processo del server, perché non sta puntando all'esterno dello spazio indirizzo della struttura, giusto? Come potrei risolvere il problema in questione? Grazie! –