在线程中创建posix共享内存
Posted
技术标签:
【中文标题】在线程中创建posix共享内存【英文标题】:posix shared memory creation in thread 【发布时间】:2018-11-30 03:50:40 【问题描述】:我是 Linux 编程的新手,所以请温柔一点! .
我正在尝试实现上述场景。这里使用fork()
创建了两个进程,每个进程都有N 个线程。
来自进程 1 的线程创建一个请求并将其加入队列 1。来自进程 2 的线程将一个请求出列并在队列 2 上发回响应。
每个请求由shmid
和size
组成,其中shmid
是这样生成的共享内存段 -
shmid = shm_open(<a random string>, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG);
if (shmid < 0)
perror("failure on shm_open");
exit(1);
if (ftruncate(*share, size) == -1)
perror("Error on ftruncate\n");
exit(-1);
我可以在创建后立即在同一个线程中打开和修改这个共享内存段
void* request = mmap(NULL, size, PROT_WRITE, MAP_SHARED, shmid, 0);
memset(str, 'w', size);
在此之后,我使用队列 1 将 shmid 传递给进程 2。
我的问题是,当进程 2 中的线程尝试使用相同的方式打开此 shmid 时,我收到 EBADF: fd is not a valid file descriptor
错误。我已经通过在进程 1 和 2 中打印值来验证出队后 shmid 是正确的。
当从不同的进程/线程创建进程时,是否无法在进程之间创建共享内存段?关于如何让它发挥作用的任何想法?
如果需要更多信息,请告诉我。
【问题讨论】:
为什么不使用消息队列呢? Unix 消息队列而不是队列?我将来可能会切换到那个。但这对我目前的问题有帮助吗?我不认为他们是相关的...... Posix 消息队列,是的。 linux.die.net/man/7/mq_overview 或其他人建议的 Unix 本地数据报套接字。为什么要通过重新发明***来让生活变得困难?使用现有的消息传递功能。 【参考方案1】:共享内存段必须在两个进程中都打开。
如果两个进程都是由fork()
从一个共同的父进程创建的,那么您可以在fork()
之前执行shm_open()
,它将被两个子进程继承。
另外,每个进程都可以调用shm_open()
,为name
参数传递相同的值。
【讨论】:
我一直在寻找替代解决方案!我的请求有可变大小,所以我不知道分配 pre-fork()
的大小。谢谢!
P.S.第二次打开共享内存时,打开它时不要设置O_TRUNC
标志。 O_TRUNC
将共享内存对象截断为 0 字节。来源 - man7.org/linux/man-pages/man3/shm_open.3.html【参考方案2】:
如果您试图访问由另一个进程创建的文件描述符,它将无法正常工作。文件描述符仅在创建它们的过程中有效。我之所以这么说是因为您看到的错误。
但是您对共享内存有正确的想法,您可以为两个进程创建一个共享的映射内存段,这可能会因竞争条件而变得棘手,每个进程中的多个线程竞争访问它,或者您可以创建一个套接字,并让您的两个进程通过该套接字或管道进行通信。
我会推荐一个用于 IPC 的 AF_UNIX 套接字,就像您尝试实现的那样。
【讨论】:
是的,如果使用队列不成功,我将不得不切换到套接字。我实施队列的唯一原因是因为它在我的要求中有所说明...... 我在想你可以在映射的内存块的头部放置一个互斥锁,然后来自两个进程的线程可以锁定和解锁。只是一个想法。 是的,我已经这样做了。我已将 posix 互斥锁和条件变量映射到共享内存,并使用它进行同步。以上是关于在线程中创建posix共享内存的主要内容,如果未能解决你的问题,请参考以下文章