当前位置: 首页 > 知识库问答 >
问题:

使用mmap从共享内存读取-分段错误

施子民
2023-03-14

我还在努力把我的头缠在共享的记忆上。我试图完成的是拥有一个豆荚数组。每个pod还将包含一个KeyValue数组。

typedef struct {
   char key[256];
   char value[256];
}keyValue;

typedef struct {
   keyValue **arr;
   int count;
}pod;

int fd;

int main(int argc, char **argv) {
   int kv_store_create(char *name) {
       return shm_open(name, O_CREAT|O_RDWR, S_IRWXU);
   }

   void kv_store_write(char *key1, char *value1) {

      static pod (*str)[28];

      ftruncate(fd, sizeof(str));

      str = (pod(*)[28])mmap(NULL, sizeof(str), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

      for (int i = 0; i < 28; i++) {
         str[i]->arr = (keyValue **)malloc(28 * sizeof(keyValue));
         for(int j = 0; j < 28; j++) {
            str[i]->arr[j] = (keyValue *)malloc(256 * sizeof(keyValue));
         }
       }

       strncpy(str[0]->arr[0]->key, key1, strlen(key1));
       strncpy(str[0]->arr[0]->value, value1, strlen(value1));
       str[0]->count = 1;
    }

   fd = kv_store_create("sharedmem");

   kv_store_write("key", "value");

因此,在这一点上,我在一个pod中有一个keyValue,如果我从同一个文件中读取共享内存,我就没有问题了。

当我试图从另一个进程中读取时,问题就出现了。我有以下文件

int main(int argc, char **argv) {

    typedef struct {
        char key[256];
        char value[256];
    }keyValue;

    typedef struct {
        keyValue **arr;
        int count;
    }pod;


    int fd = shm_open("sharedmem", O_RDWR, 0);
    if (fd < 0) {
        printf("Error... opening shm\n");
    }

    struct stat s;

    if (fstat(fd, &s) == -1) {
        printf("Error fstat\n");
    }

    pod (*str2)[28];

    str2 = (pod(*)[28])mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0);

    printf("%s", str2[0]->arr[0]->key); 

}

printf导致seg错误,我认为它试图访问没有分配任何内容的部分内存,而printf实际上会在我的第一个文件中打印。

我试图弄清楚为什么会吐出一个错误,以及我应该采取什么路线才能在两个进程之间共享一个数组结构

谢了!

共有1个答案

刘棋
2023-03-14

你说的是:

每个pod还将包含一个KeyValue数组。

但事实并非如此,因为豆荚是:

typedef struct {
   keyValue **arr;
   int count;
}pod;

它不包含keyvalue数组。它包含一个指向keyvalue*数组的指针,但是keyvalue对象本身既不在pod中,也不在arr指向的内存中。所以它们肯定不在两个进程之间共享的内存中。

因此,读取进程得到一个pod,其中包含指向所属进程中地址的指针;显然,该指针在读取器中完全没有意义,因为进程不共享内存,所以在另一个进程中拥有一个对象的地址或多或少等同于拥有一个随机数。

简而言之,您必须确保共享内存区域实际上包含您想要共享的所有对象,而不仅仅是指向它们的指针。而且由于mmap不太可能在这两个进程中返回相同的地址,因此在共享内存中插入指针,即使指向放置在共享内存中的对象,也是无用的。

 类似资料:
  • 问题内容: 在此线程中,建议在Linux中使用OP 而不是获取共享内存。我访问了这个页面,这个页面来获得一些文件,但第二个方面给出了一个模糊的例子。 几乎是新手,并且需要在两个进程之间共享一些信息(以文本形式),我应该使用该方法还是?又为什么呢 问题答案: 两种方法都是可行的。该方法比限制性更强,但更易于使用。是旧的System V共享内存模型,并且支持范围最广。/ 是用于共享内存的新POSIX方

  • 在这个线程中,建议OP使用而不是来获取Linux中的共享内存。我访问了这个页面和这个页面以获得一些文档,但是第二个页面给出了一个关于的模糊示例。 作为一个新手,并且需要在两个进程之间共享一些信息(文本形式),我应该使用方法还是?为什么呢?

  • 问题内容: 我试图在共享内存上发布一些随机的东西;出于某些奇怪的原因,阅读器没有选择发件人写的东西 这是发件人: 这是读者: 如果重新启动阅读器,则阅读器确实能够读取发送方已写入的最后一个值。 但是,如果我先启动阅读器,然后再启动发送器,则阅读器不会拾取发送器写入的所有值。 为了使这个更奇怪,如果我在SHM :: read()中取消对printf语句的注释,那么读者有时可以使用。 任何的想法? G

  • 问题内容: 我在Linux 2.6中。我有一个环境,其中2个进程通过消息传递模式的简单实现来模拟(使用共享内存)数据交换。 我有一个客户端进程(从父进程(即服务器)派生),该进程将struct(消息)写入使用以下命令创建的内存映射区域(在派生之后): 然后将此指针以链接列表的形式写入到另一个共享内存区域中的队列中,该共享内存区域对于服务器和客户端进程是通用的(因为如果在派生之前使用上面的相同代码创

  • 我一直在谷歌搜索这个问题,但还没有找到一个明确的答案,所以我希望有人对windows与Linux的共享内存段有一些了解。 在Windows中,似乎只有内存映射文件的等价物,你必须有一个实际的文件漂浮在某个地方。 我的问题是:这实际上是Windows中唯一的一种共享内存,还是它有一个api来创建非基于文件的共享内存段。

  • 我在编写一些简单的代码来自学信号量和POSIX共享内存时遇到了问题。 其思想是一个程序,即服务器,打开共享内存并向其中写入一个结构(包含信号量和数组)。然后它等待输入,输入之后信号量递增。 同时,客户端打开共享内存,等待信号量,在服务器增加信号量之后,读取结构。 服务器似乎工作正常,但是我在客户端的函数处立即遇到了一个segfault(甚至在服务器增加它之前)。我想不出哪里出了问题。 服务器代码: