2017-03-04 3 views
0

Ich versuche immer noch, meinen Kopf um Shared Memory einzuwickeln. Was ich versuche zu erreichen, ist eine Reihe von Pods. Jeder Pod enthält außerdem ein Array von keyValue.Lesen aus dem gemeinsamen Speicher mit mmap - Segmentation Fault

typedef struct { 
    char key[256]; 
    char value[256]; 
}keyValue; 

typedef struct { 
    keyValue **arr; 
    int count; 
}pod; 

int fd; 

int main(int argc, char **argv) { 
    int kv_store_create(char *name) { 
     return shm_open(name, O_CREAT|O_RDWR, S_IRWXU); 
    } 

    void kv_store_write(char *key1, char *value1) { 

     static pod (*str)[28]; 

     ftruncate(fd, sizeof(str)); 

     str = (pod(*)[28])mmap(NULL, sizeof(str), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 

     for (int i = 0; i < 28; i++) { 
     str[i]->arr = (keyValue **)malloc(28 * sizeof(keyValue)); 
     for(int j = 0; j < 28; j++) { 
      str[i]->arr[j] = (keyValue *)malloc(256 * sizeof(keyValue)); 
     } 
     } 

     strncpy(str[0]->arr[0]->key, key1, strlen(key1)); 
     strncpy(str[0]->arr[0]->value, value1, strlen(value1)); 
     str[0]->count = 1; 
    } 

    fd = kv_store_create("sharedmem"); 

    kv_store_write("key", "value"); 

Deshalb an dieser Stelle habe ich eine keyValue in einer Hülse, und wenn ich den gemeinsam genutzten Speicher aus der gleichen Datei zu lesen, ich habe keine Probleme.

Das Problem tritt auf, wenn ich versuche, von einem anderen Prozess zu lesen. Ich habe die folgende Datei

int main(int argc, char **argv) { 

    typedef struct { 
     char key[256]; 
     char value[256]; 
    }keyValue; 

    typedef struct { 
     keyValue **arr; 
     int count; 
    }pod; 


    int fd = shm_open("sharedmem", O_RDWR, 0); 
    if (fd < 0) { 
     printf("Error... opening shm\n"); 
    } 

    struct stat s; 

    if (fstat(fd, &s) == -1) { 
     printf("Error fstat\n"); 
    } 

    pod (*str2)[28]; 

    str2 = (pod(*)[28])mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0); 

    printf("%s", str2[0]->arr[0]->key); 

} 

Die printf einen seg Fehler verursacht und ich glaube, es versucht, einen Teil eines Speicher zuzugreifen, die nichts zugewiesen hat, während die printf tatsächlich in meiner ersten Datei drucken.

Ich versuche, herauszufinden, warum ein Fehler spuckt wird und welche Route sollte ich

ein Array von Strukturen zwischen zwei Prozessen zu teilen

Dank der Lage sein!

+0

[nicht die Ursache] 'strncpy (str [0] -> arr [0] -> Schlüssel, Schlüssel1, strlen (Schlüssel1));' ist * komplett * falsch. – wildplasser

Antwort

0

Was Sie sagen, ist:

Jeder Pod wird auch eine Reihe von keyValue enthalten.

Aber das ist nicht der Fall, weil eine Schote ist:

typedef struct { 
    keyValue **arr; 
    int count; 
}pod; 

die nicht eine Reihe von KeyValue enthalten. Es enthält einen Zeiger auf ein Array von KeyValue*, aber die KeyValue Objekte selbst sind weder in der pod noch in dem Speicher von arr gezeigt. Sie sind also definitiv nicht in der Erinnerung, die Sie zwischen den beiden Prozessen teilen.

So wird der Leseprozess ein pod die einen Zeiger auf eine Adresse im besitzenden Prozess enthält; Offensichtlich ist dieser Zeiger im Leser völlig bedeutungslos, da Prozesse keinen Speicher teilen, so dass eine Adresse eines Objekts in einem anderen Prozess mehr oder weniger äquivalent zu einer Zufallszahl ist.

Kurz gesagt, Sie müssen sicherstellen, dass der Shared Memory-Bereich tatsächlich alle Objekte enthält, die Sie freigeben möchten, nicht nur Zeiger auf sie. Und da es unwahrscheinlich ist, dass mmap die gleiche Adresse in den beiden Prozessen zurückgibt, ist es nicht sinnvoll, Zeiger in den gemeinsam genutzten Speicher einzufügen, selbst für Objekte, die im gemeinsamen Speicher abgelegt sind.

+0

Awesome, ich habe ein bisschen herumgespielt und es geschafft, ein Array von Pods zu teilen, die nur einen einzigen keyValue mit einem anderen Prozess enthalten, indem ich typedef struct {keyValue arr; }. Ich würde annehmen, dass ich typedef struct {keyValue * arr; } für ein Array von keyValue, ist das richtig? –

+0

@Bibik: Ein Array von 'KeyValue' ist ein' KeyValue [] '; Es * verfällt * zu einem 'KeyValue *', aber Sie sollten die beiden nicht verwechseln. Wenn Sie einen Zeigertyp eingeben, werden Sie mit ziemlicher Sicherheit selbst und jeden, der Ihren Code liest, verwirren. '*' s sind spitze und spitze Dinge sollten sichtbar sein; sonst steckst du dich selbst an. Was kompliziert wird, ist der Versuch, ein Array-Objekt mit dynamischer Größe zu erstellen, da C-Arrays immer eine feste Größe haben (selbst wenn es sich um VLAs handelt). In diesem Fall benötigen Sie einen 'KeyValue *', aber denken Sie daran, dass es nicht dasselbe ist wie ein Array. – rici

+0

@Bibik: Was bedeutet übrigens "count"? Und haben Sie wirklich vor, dass die gemeinsame Datenstruktur ein Array von 28 Arrays von 28 KeyValue's ist, also insgesamt 784 Paare? – rici