2013-01-15 2 views
7

Ich habe ein Problem, struct in eine zugeordnete Speicherdatei zu schreiben.Struktur in gemappte Speicherdatei schreiben (mmap)

Ich habe zwei Dateien nämlich mmap.write.c und mmap.read.c, und in diesen Dateien schreibe ich eine ganze Zahl in eine Datei und lese es aus der Datei.

Wenn ich struct schreiben möchten und lesen, was ich darüber nicht, da in Linie denken konnte 32 von mmap.write.c

sprintf((char*) file_memory, "%d\n", i); 

und in Zeile 25 von mmap.read.c

sscanf (file_memory, "%d", &integer); 

Es gibt keinen Unterschied zu schreiben und lesen Integer/Double/Float/Char usw., da ich Muster als zweites Argument "% d" für Integer setzen kann. Aber was ich hier schreiben werde, um struct anzugeben? Das ist mein Hauptproblem.

Die Struktur, die ich schreiben möchte und lesen:

#define CHANNELS 20 
typedef dataholder struct { 
    int value[CHANNELS]; 
    time_t time; 
    int hash; 
}dataholder; 

mmap.read.c

#include <stdlib.h> 
#include <stdio.h> 
#include <fcntl.h> 
#include <sys/mman.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include "mmap.h" 
#define FILE_LENGTH 0x10000 
int main (int argc, char* const argv[]) 
{ 
    int fd; 
    void* file_memory; 
    int integer; 
    /* Open the file. */ 
    fd = open (argv[1], O_RDWR, S_IRUSR | S_IWUSR); 
    printf("file opened\n"); 
    /* Create the memory mapping. */ 
    file_memory = mmap (0, FILE_LENGTH, PROT_READ | PROT_WRITE, 
    MAP_SHARED, fd, 0); 
    printf("memfile opened\n"); 
    close (fd); 
    printf("file closed\n"); 
    /* Read the integer, print it out, and double it. */ 
    while(1) { 
     sscanf (file_memory, "%d", &integer); 
     printf ("value: %d\n", integer); 
     usleep(100000); 
    } 
    //sprintf ((char*) file_memory, "%d\n", 2 * integer); 
    /* Release the memory (unnecessary because the program exits). */ 
    munmap (file_memory, FILE_LENGTH); 
    return 0; 
} 

mmap.write.c

#include <stdlib.h> 
#include <stdio.h> 
#include <fcntl.h> 
#include <sys/mman.h> 
#include <sys/stat.h> 
#include <time.h> 
#include <unistd.h> 
#include "mmap.h" 
#define FILE_LENGTH 0x10000 
/* Return a uniformly random number in the range [low,high]. */ 
int random_range (unsigned const low, unsigned const high) 
{ 
    unsigned const range = high - low + 1; 
    return low + (int) (((double) range) * rand()/(RAND_MAX + 1.0)); 
} 
int main (int argc, char* const argv[]) 
{ 
    int fd, i; 
    void* file_memory; 
    /* Seed the random number generator. */ 
    srand (time (NULL)); 
    /* Prepare a file large enough to hold an unsigned integer. */ 
    fd = open (argv[1], O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); 
    //lseek (fd, FILE_LENGTH+1, SEEK_SET); 
    write (fd, "", 1); 
    //lseek (fd, 0, SEEK_SET); 
    /* Create the memory mapping. */ 
    file_memory = mmap (0, FILE_LENGTH, PROT_WRITE, MAP_SHARED, fd, 0); 
    close (fd); 
    /* Write a random integer to memory-mapped area. */ 
    for(i=0; i<10000; i++) { 
     sprintf((char*) file_memory, "%d\n", i); 
     //goto a; 
     usleep(100000); 
    } 
    a: 
    /* Release the memory (unnecessary because the program exits). */ 
    munmap (file_memory, FILE_LENGTH); 
    return 0; 
} 

Dank Voraus viel in .

Antwort

10

Zuerst müssen Sie verfolgen, wo in dem Speicher, den Sie schreiben möchten, zweitens müssen Sie daran denken, dass der zugeordnete Speicher genau wie jeder andere Zeiger auf Speicher ist. Das letzte Bit ist wichtig, da dies bedeutet, dass Sie die normale Array-Indizierung verwenden können, um auf den Speicher zuzugreifen, oder Funktionen wie memcpy verwenden, um in den Speicher zu kopieren.

eine Struktur zu schreiben, haben Sie drei Möglichkeiten:

  1. die Struktur schreiben, wie sie ist, wie in einer Binärdatei. Dies bedeutet, dass Sie memcpy die Struktur an einer bestimmten Position haben müssen.

  2. Schreiben Sie die Struktur Feld für Feld als Text mit z. sprintf in die richtige Position.

  3. Behandeln Sie den Speicher als eine große Zeichenfolge und tun z. sprintf von jedem Feld in einen temporären Puffer, dann strcat, um es dem Speicher hinzuzufügen.

+0

Ich mag die zweite Möglichkeit, Sie haben zur Verfügung gestellt, einfach und leicht zu machen. Da ich es in einem Embedded-System verwende, gibt es keine Garantie, dass genug Platz ist. Danke nochmal. – totten

2

Der einfachste Weg ist, um nur einen Zeiger zu verwenden:

dataholder *dh = file_memory; 
/* now you can access dh->value, dh->time, dh->hash */ 

Da diese Struktur keine Zeiger nicht enthält, wenn Sie kopieren müssen sie in oder out, können Sie einfach zuweisen wie:

dataholder dh_other = *dh; 

oder

*dh = dh_other;