2013-02-26 29 views
6

Mam 2 procesy (Klient i Serwer), które komunikują się za pośrednictwem pamięci współdzielonej.C - Dynamiczny Array 2D (Double Pointer) - Współdzielona Pamięć

Potrzebuję utworzyć 2D Array, który jest dynamiczny (w oparciu o parametry). Tablica jest przechowywana w strukturze, a następnie zapisywana w udostępnionym segmencie.

Mogę zapisać tablicę do pamięci współdzielonej, ale nie mogę jej pobrać z innego procesu.

Kod Klient:

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]; 
       } 
      } 

Kod serwera:

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]);    
} 

dostaję "Segmentacja fault" błąd.

Dzięki.

+1

Czy adres pamięci współdzielonej jest taki sam w obu procesach? Jeśli nie, wskaźniki nie będą działać. –

+0

Tak, są takie same :) –

Odpowiedz

5

Nawet jeśli Twój obiekt shared_stuff jest w pamięci współdzielonej, nie zapisujesz tej tablicy do pamięci współdzielonej. Przydzielasz miejsce za pomocą malloc, zapisując dane do tego obszaru, a następnie wstawiając wskaźniki do tej przestrzeni w shared_stuff. malloc przydziela miejsce w bieżącym procesie 'normalnej przestrzeni adresowej, a nie w segmencie pamięci współdzielonej, który utworzyłeś. Musisz zapisać zawartość tablicy we wspólnej pamięci.

Zakładając, że w segmencie pamięci wspólnej jest wystarczająco dużo miejsca na tablicę, będziesz musiał sam zarządzać adresami, a nie korzystać z malloc. (Jeśli nie ma wystarczającej ilości wolnego miejsca, musisz zwiększyć rozmiar segmentu pamięci współużytkowanej lub przesłać informacje w kawałkach).

Możesz umieścić tablicę o zmiennej długości w segmencie pamięci wspólnej w następujący sposób.

pierwsze, tworzą strukturę, która zawiera wszystkie „Zarządzanie” potrzebne informacje, takie jak rozmiary tablicy:

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

Utwórz wskaźnik do tej struktury i ustawić go zwrócić do segmentu pamięci wspólnej:

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

Tworzenie wskaźnik do tablicy z żądanej liczby kolumn i ustawić go zwrócić do segmentu pamięci wspólnej, po początkowym strukturze:

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

(Uwaga dla C purystów: Tak, standard C nie gwarantuje, co się stanie, gdy wykonamy taką arytmetykę wskaźnikową. Jednak każda realizacja zapewniając obsługę pamięci współdzielonej musi zapewnić wsparcie dla tego rodzaju wskaźnik arytmetycznych.)

Zauważ, że sizeof *Stuff + NumberOfRows * NumberOfColumns * size(int)musi być większa niż wielkość segmentu pamięci współdzielonej. W przeciwnym razie przekroczony zostanie segment pamięci wspólnej w następnym kroku.

W następnym kroku wypełnij tablicę danymi: Przypisz wartości do elementów data_store, tak jak w przypadku normalnej dwuwymiarowej tablicy.

W serwerze ustaw Stuff w ten sam sposób. Następnie, po napisaniu przez klienta segmentu pamięci wspólnej, odczytaj liczby wierszy i kolumn z Stuff. Następnie ustaw data_store w ten sam sposób.Następnie przeczytaj z data_store.

+0

Przepraszam, zapomniałem wspomnieć Mam to powyżej; 'shared_stuff = (struct shared_use_st *) shm;' Gdzie SHM jest wynikiem shmat;
\t '/ * attatch segment przestrzeni danych */ \t jeśli ((SHM = shmat (shmid NULL, 0)) == (char *) - 1) \t { \t \t perror ("shmat"); \t \t _Ekit (1); \t} \t printf ("[+] Segment Attatched \ n"); ' Napisałem ten testowy fragment kodu w kliencie, i wyprowadza dokładnie to, czego się spodziewam; 'printf (" TEST \ n \ n "); dla (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

Twój komentarz jest zgodny z moją diagnozą. Kod w kliencie drukuje to, czego oczekujesz, ponieważ dane znajdują się w oczekiwanych miejscach w przestrzeni adresowej klienta. Jednak dane nie są widoczne w przestrzeni adresowej serwera. Tylko struktura wskazywana bezpośrednio przez 'shared_stuff' znajduje się we wspólnym segmencie, ponieważ ustawiasz' shared_stuff', aby wskazywał na wspólny segment. Wskaźniki wewnątrz tej struktury wskazują miejsca poza wspólnym segmentem, miejsca przydzielone przez 'malloc'. Ponieważ te miejsca znajdują się poza wspólnym segmentem, nie są widoczne w procesie serwera. –

+0

Rozumiem. Jeśli zrobię; 'shared_stuff-> written_by_you = 1;' jest to widoczne w procesie serwera, ponieważ nie wskazuje poza przestrzenią adresową struktury, prawda? Jak mam rozwiązać problem? Dzięki! –