2013-01-15 43 views
7

Tôi gặp sự cố khi viết cấu trúc vào tệp bộ nhớ được ánh xạ.Viết cấu trúc cho tệp bộ nhớ được ánh xạ (mmap)

Tôi có hai tệp cụ thể là mmap.write.c và mmap.read.c và trong các tệp này, tôi đang viết một số nguyên cho một tệp và đọc tệp đó từ tệp.

Khi tôi muốn viết struct và đọc nó, tôi không thể nghĩ về điều đó vì trong dòng 32 của mmap.write.c

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

và phù hợp 25 của mmap.read.c

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

Không có sự khác biệt để viết và đọc số nguyên/đôi/float/char vv vì tôi có thể đặt mẫu làm đối số thứ hai "% d" cho số nguyên. Nhưng những gì tôi sẽ viết ở đây để chỉ ra struct? Đó là vấn đề chính của tôi.

Các struct mà tôi muốn viết và đọc:

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

Thanks a lot trước .

Trả lời

10

Trước hết bạn phải theo dõi trong đó trong bộ nhớ bạn muốn ghi, thứ hai bạn phải nhớ rằng bộ nhớ được ánh xạ giống như bất kỳ con trỏ nào khác vào bộ nhớ. Bit cuối cùng là quan trọng, vì điều này có nghĩa là bạn có thể sử dụng chỉ mục mảng bình thường để truy cập vào bộ nhớ, hoặc sử dụng các hàm như memcpy để sao chép vào bộ nhớ.

Để viết một cấu trúc, bạn có ba lựa chọn:

  1. Viết cấu trúc như nó vốn có, giống như trong một tập tin nhị phân. Điều này có nghĩa là bạn phải memcpy cấu trúc đến một vị trí được chỉ định.

  2. Viết cấu trúc, trường theo trường, dưới dạng văn bản sử dụng ví dụ: sprintf đến đúng vị trí.

  3. Xử lý bộ nhớ dưới dạng một chuỗi lớn và thực hiện ví dụ: sprintf của mỗi trường vào bộ đệm tạm thời, sau đó strcat để thêm nó vào bộ nhớ.

+0

tôi thích cách thứ hai bạn đã cung cấp, đơn giản và dễ thực hiện. Vì tôi sử dụng nó trong một hệ thống nhúng nên không có đảm bảo có đủ không gian. Cám ơn bạn một lần nữa. – totten

2

Cách đơn giản nhất là chỉ cần sử dụng một con trỏ:

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

Kể từ struct này không chứa bất kỳ gợi ý, nếu bạn cần phải sao chép nó vào hoặc ra, bạn chỉ có thể gán nó, như:

dataholder dh_other = *dh; 

hoặc

*dh = dh_other; 
Các vấn đề liên quan