【问题标题】:Does mmap share memory with all processes?mmap 是否与所有进程共享内存?
【发布时间】:2012-07-29 03:16:33
【问题描述】:

当我这样做时:

myProgram.h
myProgram.c

    struct PipeShm
    {
    // all my fields
    // more 
    // ...

    };



    struct PipeShm myPipe = { /* initialization for all fields */ };
    struct PipeShm * sharedPipe = &myPipe;

void func()
{
 sharedPipe = mmap (NULL, sizeof * sharedPipe, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, -1, 0);

}

当我mmap 指针sharedPipe 时,如果我从main() 调用myProgram 代码中的任何方法,所有进程是否会共享我与myPipe 结构共享的确切共享内存?

或者每个新创建的孩子都会有一个自己的新myPipe

问候

编辑:

这是在我阅读了 cmets 和答案之后:现在进行了更改,并且仅在分配段后才初始化段的值:

#include "my_pipe.h"

struct PipeShm * sharedPipe = NULL;



int shm_pipe_init()
{
    if (!sharedPipe)
    {
        int myFd = shm_open ("/myregion", O_CREAT | O_TRUNC | O_RDWR, 0600);

        if (myFd == -1)
            error_out ("shm_open");

        // Allocate some memory in the region - We use ftruncate, write(2) would work just as well
        int retAlloc = ftruncate (myFd, sizeof * sharedPipe);
        if (retAlloc < 0)
            error_out("ftruncate");


        sharedPipe = mmap (NULL, sizeof * sharedPipe,
                PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, myFd, 0);

        if (!sem_init (&sharedPipe->semaphore, 1, 0))
        {
            sharedPipe->init = TRUE;
            sharedPipe->flag = FALSE;
            sharedPipe->ptr1 = NULL;
            sharedPipe->ptr2 = NULL;
            sharedPipe->status1 = -10;
            sharedPipe->status2 = -10;
            sharedPipe->semaphoreFlag = FALSE;
            sharedPipe->currentPipeIndex = 0;

        }
        else
            perror ("shm_pipe_init");
    }
    return 1;   // always successful
}

但问题仍然存在,共享内存似乎在进程之间并没有如此共享,因为在运行和分叉该 main 时:

int main()
{
    int spd, pid, rb;
    char buff[4096];

    fork();
    shm_pipe_init();

        // more
        return 0;
}

我仍然得到输出,模拟只有一个进程正在运行的行为(而不是多个输出,我只得到一个 onecouple ,取决于进程之间的竞争条件)。

【问题讨论】:

  • “所有进程”是什么意思?系统中的所有进程,还是原来的所有子进程等等?
  • @tbert: 所有进程 - 表示子进程、孙子进程...等
  • 书写提示:英文标点(逗号、冒号、分号、句号、问号等)前没有空格。

标签: c linux operating-system shared-memory mmap


【解决方案1】:

每个都有自己的,因为对 指针 sharedPipe 的更改不会影响myPipe

【讨论】:

  • 好的,那么我该如何更改以上内容以使所有进程(子进程)具有相同的内存?谢谢
  • 他们已经这样做了。 sharedPipe您必须取消引用它才能访问这些字段。
  • 你的意思是:struct PipeShm * sharedPipe = myPipe;?如果是这样,这不会编译。
  • @ron,我建议您应该执行 ..shm_open(获取共享内存)、ftruncate(将内存大小设置为您的结构大小)然后 mmap(获取指针,然后通过访问结构的成员对其进行初始化)。此映射内存(即指针)应该可用于您所指的所有进程。
  • @Tanmoy:请看修改后的帖子,我按照你的建议做了,但问题仍然存在。
【解决方案2】:

让我们逐步了解您在此处所做的具体操作

struct PipeShm myPipe = { /* initialization for all fields */ };

这会将PipeShm 结构分配为全局变量

struct PipeShm * sharedPipe = &myPipe;

这会创建一个指向先前创建的结构的指针。

现在您将指针 sharedPipe 修改为 mmap 返回的内容(可能是共享内存区域的地址)而不是您之前分配的结构(注意:myPipe 仍然存在 - 只是没有指向)。

sharedPipe = mmap (NULL, sizeof * sharedPipe, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, -1, 0);

据我所知,您也没有尝试访问sharedPipe。所以现在,你基本上有一个全局变量一段共享内存(这两个似乎都没有使用)。

这就是我不太确定您要做什么的地方。

如果您想访问共享内存,您需要在mmap 返回后取消引用sharedPipe 指针(如果是,那么全局变量的意义何在?)。

如果您想访问全局变量,只需将其作为myPipe 访问(如果是,mmap 是为了什么?)。

如果您想同时访问两者,请结合使用上述方法(如果是,那么struct PipeShm * sharedPipe = &amp;myPipe; 的意义何在?)

【讨论】:

  • 请看修改后的帖子,我照你说的做了……你是对的!
【解决方案3】:

如果你打算多次调用这个程序,答案是“不”。如果您打算在创建映射后分叉,答案是“是”。

匿名映射没有基础文件。因此,创建匿名映射的进程无法指定它想要的现有映射(这也不是预期的用途,您应该获得一个新的、独立的映射)。因此对第一种情况说“不”。

共享映射允许拥有相同映射的所有进程访问相同的物理内存。这意味着,如果您在创建映射后fork,那么fork 将主要以通常的方式工作,将进程拥有的所有页面标记为写时复制除了映射中的页面.父母和孩子都将保留映射的页面,并且能够通过指针访问相同的物理内存(顺便说一下,这意味着页面甚至也将具有相同的虚拟地址——这映射文件时通常不是您可以依赖的东西,但在这种情况下,操作系统别无选择,只能确保是这种情况)。

手册页对匿名映射和共享映射的组合或究竟应该发生什么仍然含糊其辞,但 TLPI 第 49.7 章明确提到 MAP_SHARED|MAP_ANONYMOUS

[...] 之后调用 fork(),然后,因为 fork() 生成的子进程继承了映射,所以两个进程共享内存区域。

因此对于第二种情况“是”。

回复:已编辑帖子
错误的顺序:

fork();
shm_pipe_init();

首先分叉,然后初始化共享内存。它将创建一个共享(读作 share-able,如果进程再次分叉,它可能会在将来共享,但它不会神奇地与父级共享!)映射 对于每个进程,分别。

然后,您有 两个 映射,每个进程中都有一个,它们将由它们各自的子进程和孙子进程(如果有)共享,但这无助于实现您想要的。它们是“共享”的这一事实并不重要,它们是不同的映射,并且对于各自的其他进程来说是未知的。

首先创建映射,然后分叉。这将创建 一个 两个进程确实拥有/共享的共享映射,并且可以用于预期目的。

(此外,您对fork 的使用并非完全错误,但有点奇怪……您通常应该检查返回值,因此您知道哪个是父级,哪个是子级。也不是fork 不能失败。当然,如果这无关紧要,因为父母和孩子总是 100% 相同,而且你不关心失败,那很好。通常,人们通常想知道,不过。)

【讨论】:

    猜你喜欢
    • 2014-02-14
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 2014-10-01
    • 2011-06-26
    • 1970-01-01
    相关资源
    最近更新 更多