2013-01-15 9 views
7

Mam problem z wpisaniem struct do zmapowanego pliku pamięci.Zapisywanie struct do zmapowanego pliku pamięci (mmap)

Mam dwa pliki mianowicie mmap.write.c i mmap.read.c, a w tych plikach piszę liczbę całkowitą do pliku i odczytuję go z pliku.

Gdy chcę napisać struct i czytać, nie mogę myśleć o tym, że skoro w linii 32 mmap.write.c

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

aw linii 25 mmap.read.c

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

Nie ma różnicy, aby pisać i czytać liczbę całkowitą/podwójną/zmiennoprzecinkową/char itp., Ponieważ mogę umieścić wzór jako drugi argument "% d" dla liczby całkowitej. Ale co napiszę tutaj, aby wskazać struct? To jest mój główny problem.

Struct że chcę pisać i czytać:

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

Bardzo dziękuję z góry .

Odpowiedz

10

Przede wszystkim musisz śledzić gdzie w pamięci, którą chcesz napisać, po drugie musisz pamiętać, że zamapowana pamięć jest jak każdy inny wskaźnik do pamięci. Ostatni bit jest ważny, ponieważ oznacza to, że możesz użyć normalnego indeksowania tablicy w celu uzyskania dostępu do pamięci lub użyć funkcji, takich jak memcpy do skopiowania do pamięci.

Aby napisać strukturę, masz trzy możliwości:

  1. napisać strukturę jak jest, podobnie jak w pliku binarnym. Będzie to oznaczać, że musisz memcpy strukturę do określonej pozycji.

  2. Napisz strukturę, pole po polu, jako tekst za pomocą np. sprintf do poprawnej pozycji.

  3. Traktuj pamięć jako jeden duży ciąg i wykonaj np. sprintf każdego z pól do bufora tymczasowego, a następnie strcat, aby dodać go do pamięci.

+0

Lubię drugi sposób pod warunkiem, proste i łatwe do zrobienia. Ponieważ używam go w systemie wbudowanym, nie ma gwarancji, że jest wystarczająco dużo miejsca. Jeszcze raz dziękuję. – totten

2

Najprostszym sposobem jest po prostu użyć wskaźnika:

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

Ponieważ ta struktura nie zawiera żadnych wskazówek, jeśli trzeba go skopiować lub pomniejszyć, można po prostu przypisać go, jak:

dataholder dh_other = *dh; 

lub

*dh = dh_other;