将结构体写入映射的内存文件(mmap)

8

我有一个问题,需要将结构体写入映射的内存文件。

我有两个文件,分别是mmap.write.c和mmap.read.c,在这些文件中,我将一个整数写入文件并从文件中读取它。

当我想要写入结构体并读取它时,我无法想到如何做,因为在mmap.write.c的第32行

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

并且在mmap.read.c的第25行

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

对于整数/双精度浮点数/单精度浮点数/字符等的写入和读取没有任何区别,因为我可以将模式作为第二个参数“%d”放置在整型中。但是当我要表示结构时,我该写什么?这是我主要的难点。

我想要写入和读取的结构:

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

非常感谢您提前的帮助。

2个回答

12

首先,你需要追踪你想要写入的内存中哪里,其次需要记住映射内存就像任何指向内存的指针一样。最后一个细节很重要,这意味着你可以使用常规的数组索引来访问内存,或者使用诸如memcpy之类的函数将数据复制到内存中。

要写一个结构体,你有三种选择:

  1. 将结构体按原样写入,就像在二进制文件中一样。这意味着你必须将结构体memcpy到指定位置。

  2. 逐个字段地以文本形式编写结构体,使用sprintf将其写入正确的位置。

  3. 将内存视为一个大字符串,并使用sprintf将每个字段格式化到临时缓冲区中,然后使用strcat将其添加到内存中。


我喜欢你提供的第二种方式,简单易行。由于我在嵌入式系统中使用它,无法保证有足够的空间。再次感谢。 - totten

4
最简单的方法是只使用一个指针:
dataholder *dh = file_memory;
/* now you can access dh->value, dh->time, dh->hash */

由于这个结构体不包含任何指针,如果您需要将其复制进或复制出来,可以直接进行赋值操作:

dataholder dh_other = *dh;

或者

*dh = dh_other;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接