无法在两个进程之间使用 mmap 共享内存共享数据

发布于 2025-01-19 23:02:51 字数 1325 浏览 4 评论 0原文

我有两个这样的代码。

发件人:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
//

//Globals
void *shmem = NULL;


int main()
{
    shmem = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    if(fork() == 0)
    {
        sleep(1);
        printf("%s\n", (char*)shmem);
        exit(0);
    }
    else
    {
        strcpy((char*)shmem, "Hello, world!");
        strcpy((char*)shmem, "get putin!");
        wait(NULL);
    }
    return 0;
}

接收器/读者:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
//

//Globals
void *shmem = NULL;


int main()
{
    shmem = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 
        printf("%s\n", (char*)shmem);
    return 0;
}

需求: 1。 当我运行第一个使用MMAP创建的SHM创建的程序时,我应该能够验证我阅读的内容是否正确使用分叉过程。 2。当我运行第二个程序时,它应该阅读第一个过程所写的内容。 请注意,我不应该将使用SHM_OPEN创建的文件用于此目的。不需要磁盘文件/文件描述符,我应该能够创建SHM以使两个过程彼此写入/读取。

问题:

  1. 第一个程序将正确打印父母所写的内容。但是,当您在第一个完成写作后运行第二个程序时,第二个进程会看到空白,看起来如此,因为这两个过程都是不同的过程,因此共享存储位置不同。

如何在不使用常见的FD或文件的情况下确保MMAP将相同的内存位置返回两个进程?

I have two pieces of code like this.

Sender:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
//

//Globals
void *shmem = NULL;


int main()
{
    shmem = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    if(fork() == 0)
    {
        sleep(1);
        printf("%s\n", (char*)shmem);
        exit(0);
    }
    else
    {
        strcpy((char*)shmem, "Hello, world!");
        strcpy((char*)shmem, "get putin!");
        wait(NULL);
    }
    return 0;
}

Receiver/Reader :

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
//

//Globals
void *shmem = NULL;


int main()
{
    shmem = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 
        printf("%s\n", (char*)shmem);
    return 0;
}

Requirement:
1.
When i run the first program that writes to SHM created using mmap, i should be able to verify whether what i read is right using a forked process.
2. When i run second program its supposed to read what the first process wrote.
Note that I SHOULD NOT BE USING FILES created using SHM_OPEN for this purpose. Without need of disk files/ file descriptors i should be able to create SHM to make both processes write/read to each other.

Problem:

  1. The first program will print correctly what the parent process wrote. But when you run the second program after the first finishes writing, the second process sees blank, looks so because both are different processes, so different shared memory locations.

How to ensure mmap returns same memory location to both processes, without using common fd or file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

亣腦蒛氧 2025-01-26 23:02:51

当我运行第二个程序时,它应该阅读第一个过程所写的内容。请注意,我不应该将使用SHM_OPEN创建的文件用于此目的。不需要磁盘文件/文件描述符,我应该能够创建SHM以使两个过程彼此写入/读取。

不,那是不是正确的。

您只能将map_anonymous与程序和叉子一起使用。该程序终止时,它是私有映射。

这对您从第一个程序中分配的孩子来说效果很好。

但是,一个单独的程序无法访问该数据,没有的使用(例如,使用open> Openshm_open创建的文件)。

而且,根据shm_open的注释,创建者必须使用ftruncate将文件放到正确的大小。

也许,您可能希望考虑使用SYSV共享内存(例如shmgetshmat等)。


这是校正后的第一个程序:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
//

//Globals
void *shmem = NULL;

int
main()
{

#ifdef SHM
    int fd = shm_open("/abc",O_RDWR | O_CREAT,0644);
#else
    int fd = open("/tmp/abc",O_RDWR | O_CREAT,0644);
#endif

    ftruncate(fd,4096);

    shmem = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
        MAP_SHARED, fd, 0);

    if (fork() == 0) {
        sleep(1);
        printf("%s\n", (char *) shmem);
        exit(0);
    }
    else {
        strcpy((char *) shmem, "Hello, world!");
        strcpy((char *) shmem, "get putin!");
        wait(NULL);
    }

    close(fd);

    return 0;
}

这是更正的第二个程序:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
//

//Globals
void *shmem = NULL;

int
main()
{

#ifdef SHM
    int fd = shm_open("/abc",O_RDWR,0644);
#else
    int fd = open("/tmp/abc",O_RDWR,0644);
#endif
    if (fd < 0) {
        perror("abc");
        exit(1);
    }

    shmem = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
        MAP_SHARED, fd, 0);
    printf("%s\n", (char *) shmem);

    close(fd);
#ifdef SHM
    shm_unlink("/abc");
#else
    unlink("/tmp/abc");
#endif

    return 0;
}

When i run second program its supposed to read what the first process wrote. Note that I SHOULD NOT BE USING FILES created using SHM_OPEN for this purpose. Without need of disk files/ file descriptors i should be able to create SHM to make both processes write/read to each other.

No, that is not correct.

You can only use MAP_ANONYMOUS with a program and a process that it forks. It is a private mapping that disappears when the program terminates.

This works fine for the child you fork from your first program.

However, a separate program has no way to access that data without the use of a backing store (e.g. file created with open or shm_open).

And, per the comments in shm_open, the creator has to use ftruncate to enlarge the file to the correct size.

Perhaps, you may wish to consider using SysV shared memory (e.g. shmget, shmat, etc.).


Here is the corrected first program:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
//

//Globals
void *shmem = NULL;

int
main()
{

#ifdef SHM
    int fd = shm_open("/abc",O_RDWR | O_CREAT,0644);
#else
    int fd = open("/tmp/abc",O_RDWR | O_CREAT,0644);
#endif

    ftruncate(fd,4096);

    shmem = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
        MAP_SHARED, fd, 0);

    if (fork() == 0) {
        sleep(1);
        printf("%s\n", (char *) shmem);
        exit(0);
    }
    else {
        strcpy((char *) shmem, "Hello, world!");
        strcpy((char *) shmem, "get putin!");
        wait(NULL);
    }

    close(fd);

    return 0;
}

Here is the corrected second program:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
//

//Globals
void *shmem = NULL;

int
main()
{

#ifdef SHM
    int fd = shm_open("/abc",O_RDWR,0644);
#else
    int fd = open("/tmp/abc",O_RDWR,0644);
#endif
    if (fd < 0) {
        perror("abc");
        exit(1);
    }

    shmem = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
        MAP_SHARED, fd, 0);
    printf("%s\n", (char *) shmem);

    close(fd);
#ifdef SHM
    shm_unlink("/abc");
#else
    unlink("/tmp/abc");
#endif

    return 0;
}
临走之时 2025-01-26 23:02:51

根据定义,每次使用 MAP_ANONYMOUS 调用 mmap 都会返回一个不同的、独立的内存块。因此,共享这一点的唯一方法是在一个进程中调用 mmap 一次,然后在 mmap 之后派生一个子进程(并且调用 exec,因为这将清除所有映射)。

如果您想对 mmap 进行两次调用(在两个不同的进程中,如您所描述的)引用同一共享内存块,则它们必须具有对该共享事物的某种引用或句柄。这个“句柄”是 mmap 的 fd 参数——这是唯一的方法。因此,您必须让两个程序在某个类似内存的对象(可能是文件、共享内存对象或可映射设备)上打开文件描述符,然后将其传递给 mmap。

By definition, every call to mmap with MAP_ANONYMOUS returns a different, indepedent memory block. So the only way to share this is to call mmap once, in one process, and then fork a child after the mmap (and not call exec, as that will clear all mappings).

If you want to have two calls to mmap (in two different processes, like you describe) refer to the same block of shared memroy they must have some sort of reference or handle to that shared thing. That "handle" is the fd argument to mmap -- that's the only way to do it. So you must have the two programs open a file descriptor on some memory-like object (might be a file, or a shared memory object, or a mappable device) that they can then pass to mmap.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文