0

我有一个在内存中生成大量数据的 C 程序,我需要在内存中共享这些数据的一个特定部分,以便另一个进程可以读取它。

我试图用mmap它来做这件事,但我没有取得太大的成功。这是我的代码:

//Code above generates a pointer to the memory section I need to share, named addr

if (infoBlock->memory_size == 1073741824) { //This is the data block I need to share
   int err, fd;
   fd = open("/tmp/testOutput", (0_RDWR | 0_CREAT), S_IWUSR);
   if (fd < 0) {
         perror("Couldn't create output file\n");
         goto failedExit;
    }

    unsigned *p = mmap(addr, 1073741824, PROT_READ, (MAP_SHARED | MAP_FIXED), fd, 0);
    if (!p) {perror("mmap failed"); goto failedExit; }
    printf("p is now: %p\n", p); //This should point to the shared mapping
    printf("%u\n", *p); //Try to print out some data from the mapping

}

运行程序后,我可以看到文件 /tmp/testOutput 在那里,但它的大小为 0。我不确定这是否是内存映射的正常现象,因为它在技术上不是一个文件。此外,我的程序中的所有输出都指向相同的内存地址。

我还可以看到 /proc/PID/maps 中存在的内存映射,并引用了 /tmp/testOutput。

一切似乎都在运行,但是当涉及到取消引用指针时,程序退出了,我假设这是因为我做错了映射,并且指针指向了它不应该指向的东西。

如果有人能发现我做错了什么,或者可以提供一些建议,将不胜感激。

谢谢!

4

2 回答 2

5

您已经将与该文件关联的存储(或试图)映射到您的进程中,并且您坚持将其映射到您已经用于其他东西的地址(大概addr是以某种方式分配的)。

您没有说实际上是否p确实有您请求的地址,并且正如怀疑者指出的那样,您的错误检查被破坏了。

你的困惑:

事后,您不能将任意堆或其他进程内存页面与文件相关联。您必须在文件系统中分配它们,然后映射它们。(有一种方法可以使用 vmsplice 将它们与 UNIX 管道相关联,尽管它并不完全符合您的要求)。

请注意,该MMAP_FIXED标志只会将您的数据占用的页面替换为与文件关联的新页面。如果没有该标志,地址提示将被忽略,映射将被放置在其他地方。

解决方案:

  1. 在映射文件之前将文件ftruncate到您想要的大小(这会在文件系统中分配存储空间)
  2. 映射它然后填充它
  3. 修复你的mmap错误检查

如果您无法更改分配方案,您可以管理的最好方法是将进程本地内存复制write到映射中,在这种情况下,您最好将其复制到文件中。

理想的情况是这样的:

void *alloc_mmap(const char *filename, size_t length)
{
    int fd;
    fd = open(filename, (0_RDWR | 0_CREAT), S_IWUSR);
    if (fd < 0) {
        perror("Couldn't create output file\n");
        return NULL;
    }
    if (ftruncate(fd, length)) {
        perror("Couldn't grow output file\n");
        close(fd);
        return NULL;
    }

    void *p = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
    if (p == -1) {
        perror("mmap failed");
        close(fd);
        return NULL;
    }
    close(fd);
    return p;
}

// now you've allocated your memory, you can populate it and it will be
// reflected in the file
于 2013-02-22T16:59:28.613 回答
1

这是 mmap 手册页的摘录。

   On  success,  mmap() returns a pointer to the mapped area.  On error, the value
   MAP_FAILED (that is, (void *) -1) is returned, and errno is set  appropriately.
   On  success,  munmap()  returns 0, on failure -1, and errno is set (probably to
   EINVAL).

测试成功应该改为测试mmap的-1返回值。然后检查 errno 值。HTH。

于 2013-02-22T16:53:22.067 回答