2013-01-15 1 views
7

Ho un problema per scrivere la struttura in un file di memoria mappato.Scrittura della struttura sul file di memoria mappato (mmap)

Ho due file vale mmap.write.c e mmap.read.c, e in questi file, sto scrivendo un intero in un file e leggendolo dal file.

Quando ho voglia di scrivere struct e leggere, non potevo pensare che, dal momento in linea 32 della mmap.write.c

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

e in linea 25 di mmap.read.c

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

Non c'è alcuna differenza per scrivere e leggere integer/double/float/char ecc. Poiché posso inserire pattern come secondo argomento "% d" per intero. Ma cosa scriverò qui per indicare la struttura? Questo è il mio problema principale

La struct che voglio scrivere e leggere:

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

Grazie mille in anticipo .

risposta

10

Prima di tutto è necessario tenere traccia di dove nella memoria che si desidera scrivere, in secondo luogo è necessario ricordare che la memoria mappata è come qualsiasi altro puntatore alla memoria. L'ultimo bit è importante, in quanto ciò significa che è possibile utilizzare la normale indicizzazione di array per accedere alla memoria o utilizzare funzioni come memcpy da copiare nella memoria.

Per scrivere una struttura, sono disponibili tre opzioni:

  1. Scrivi la struttura così com'è, come in un file binario. Ciò significa che è necessario memcpy la struttura in una posizione specificata.

  2. Scrivere la struttura, campo per campo, come testo utilizzando ad es. sprintf nella posizione corretta.

  3. Trattare la memoria come una stringa grande e ad es. sprintf di ciascun campo in un buffer temporaneo, quindi strcat per aggiungerlo alla memoria.

+0

mi piace il secondo modo hai fornito, semplice e facile da fare. Dal momento che lo uso in un sistema embedded non vi è alcuna garanzia che ci sia spazio sufficiente. Grazie ancora. – totten

2

Il modo più semplice è quello di utilizzare solo un puntatore:

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

Dal momento che questa struct non contiene i puntatori, se è necessario copiarlo dentro o fuori, si può semplicemente assegnare esso, come:

dataholder dh_other = *dh; 

o

*dh = dh_other;