使用mmap共享进程内存

Ton*_*ony 0 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

}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

谢谢!

Use*_*ess 5

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

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

你的困惑:

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

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

解决方案:

  1. 映射之前将文件命名为所需的大小(这会在文件系统中分配存储)
  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
Run Code Online (Sandbox Code Playgroud)