使用mmap共享进程内存

时间:2013-02-22 16:43:08

标签: c linux ipc mmap

我有一个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。

所有东西似乎都在运行,但是当取消引用指针时,程序退出,我假设这是因为我完成了映射错误,并且指针指向它不应该的东西。 / p>

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

谢谢!

2 个答案:

答案 0 :(得分:5)

您已将与该文件相关联(或已尝试过)的存储映射到您的流程中,并且您已坚持将其映射到您已用于其他内容的地址(可能是addr以某种方式分配。)

您没有说p是否确实拥有您请求的地址,而且正如嫌疑人所指出的那样,您的错误检查已被破坏。

你的困惑:

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

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

解决方案:

  1. ftruncate在映射之前将文件设置为所需大小(这会在文件系统中分配存储空间)
  2. 映射它并然后填充它
  3. 修复您的mmap错误检查
  4. 如果您无法更改分配方案,那么您可以管理的最佳方法是将流程本地内存复制到映射中,在这种情况下,您可能只需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
    

答案 1 :(得分: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返回值。然后检查错误 值。 HTH。