【问题标题】:c - can't read pointers from struct using mmapc - 无法使用 mmap 从结构中读取指针
【发布时间】:2015-11-20 14:02:43
【问题描述】:

我正在尝试使用mmap 将图形存储在文件中,因此我读写速度更快,但我无法读取使用 malloc 创建的字段结构字段(我无法将它们设为数组)

问题是我无法从文件中读回归档的map[i].nodes->vertexKey
(我认为是因为它是使用malloc 创建的)

我的代码是:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#define COUNT 10
#define FILESIZE (  COUNT * sizeof(struct vertex))
struct node{
    int vertexKey ;
    struct node *nextNode;
};
struct vertex {
    int vertexKey;
    struct node *nodes;
};
int readMmap(){
    const char *filepath = "/tmp/mmapped.bin";
    int fd = open(filepath, O_RDWR  , (mode_t)0600);
    if (fd == -1)
    {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }
    struct stat fileInfo = {0};    
    if (fstat(fd, &fileInfo) == -1)
    {
        perror("Error getting the file size");
        exit(EXIT_FAILURE);
    }
    if (fileInfo.st_size == 0)
    {
        fprintf(stderr, "Error: File is empty, nothing to do\n");
        exit(EXIT_FAILURE);
    }
    printf("File size is %ji\n", (intmax_t)fileInfo.st_size);
    struct vertex *map = mmap(0, FILESIZE , PROT_READ, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED)
    {
        close(fd);
        perror("Error mmapping the file");
        exit(EXIT_FAILURE);
    }
    for (off_t i = 0; i < COUNT; i++)
    {
        printf("%d  |", map[i].vertexKey );
        // i can't read map[i].nodes->vertexKey
        printf("%d  \n", map[i].nodes->vertexKey );
        printf("\n" );
    }
    // Don't forget to free the mmapped memory
    if (munmap(map, fileInfo.st_size) == -1)
    {
        close(fd);
        perror("Error un-mmapping the file");
        exit(EXIT_FAILURE);
    }   
    // Un-mmaping doesn't close the file, so we still need to do that.
    close(fd);
    return 0;
}

int writeMmap(){
    const char *filepath = "/tmp/mmapped.bin";
    int fd = open(filepath, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
    if (fd == -1){
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }
    if (lseek(fd, FILESIZE-1, SEEK_SET) == -1){
        close(fd);
        perror("Error calling lseek() to 'stretch' the file");
        exit(EXIT_FAILURE);
    }
    if (write(fd, "", 1) == -1){
        close(fd);
        perror("Error writing last byte of the file");
        exit(EXIT_FAILURE);
    }
    struct vertex *map = mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED)    {
        close(fd);
        perror("Error mmapping the file");
        exit(EXIT_FAILURE);
    }
    for (size_t i = 0; i < COUNT; i++){
        struct vertex ss ;
        ss.vertexKey=i;
        struct node *n1 = (struct node*)malloc(sizeof(struct node));
        n1->nextNode =NULL ;
        n1->vertexKey=i*10 ;
        ss.nodes = n1 ;
        map[i] = ss;
    }
    // Write it now to disk
    if (msync(map, 100, MS_SYNC) == -1)
    {
        perror("Could not sync the file to disk");
    }
    // Don't forget to free the mmapped memory
    if (munmap(map, 100) == -1)
    {
        close(fd);
        perror("Error un-mmapping the file");
        exit(EXIT_FAILURE);
    }
    // Un-mmaping doesn't close the file, so we still need to do that.
    close(fd);
    return 0;
}

【问题讨论】:

  • 具体说明您观察到的问题。你期待什么结果,你看到了什么?哪里有错误信息?你能用更小的示例代码重现这个问题吗?
  • @JohnBollinger 我编辑了问题
  • 仅从问题标题来看,我推测您可能在 mmapped 文件中记录了指向进程私有内存的指针。这样的指针 value 应该可以很好地通过映射的内存,但在它指向的内存的进程之外没有意义。
  • 是的,我认为这就是问题所在......我的问题是如何解决它......谢谢
  • 在担心mmap 之前,我会尝试让代码与readwrite 一起工作。在你学会跑步之前先学会走路。您需要不涉及指针的数据在磁盘上的表示。

标签: c pointers struct malloc mmap


【解决方案1】:

这真的需要多快?为您的持久格式使用内存映像是一个有问题的做法——您需要它在更大的计划中取得相当大的胜利,这样它才值得,如果它甚至可能的话。

如果您想要数据的持久表示,那么该表示需要是自包含的。不支持指针本身,但您可以在它们的位置使用对象表(实际上是数组)的索引。如果索引是隐式的会更好,但这对您来说可能还不够。很抱歉含糊其辞,但我需要更好地了解您的数据的特征,然后才能提出任何具体建议。

【讨论】:

  • 感谢您的回答:我正在尝试实现一种使用邻接列表存储大型图形的方法:女巫意味着我需要快速访问特定顶点,这就是我坚持使用 mmap 的原因
  • mmap() 用于快速、随机访问 I/O 或共享内存。常规的内存数据结构可以更好地提供快速、通用的运行时访问。您似乎在 I/O 轨道上,因此您所追求的是在外部和内部表示之间来回 转换mmap() 或许可以提供帮助,但它不允许您将外部和内部表示合并为一个。
  • 如果我理解正确你是说我不能在这里使用 mmap
  • 我不知道您是否可以将mmap() 用于您的目的,但是您通过mmap() 编写的文件格式不适用于图形数据的序列化/外部化.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-01
  • 1970-01-01
  • 2020-10-16
  • 1970-01-01
  • 2021-04-07
  • 1970-01-01
相关资源
最近更新 更多