从一个进程创建多个共享内存

Posted

技术标签:

【中文标题】从一个进程创建多个共享内存【英文标题】:Multiple shared memory creation from one process 【发布时间】:2012-07-26 12:52:10 【问题描述】:

一个进程不能创建两个IPC共享内存段吗?

我正在尝试从一个进程创建两个共享内存,一个用于与单独的进程共享数据,另一个用于与其子进程共享。我正在使用shmget,我也尝试使用ipcs获取系统中的共享内存信息。其输出是这样的:

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x0beefbaf 0          root       666        225544     4                       
0x00000000 98305      root       666        4          0                       

以上输出显示确实创建了两个共享段,但 shmget 仅返回 0 作为其输出。因此,一个共享内存段被附加了两次。

shmget 有什么问题,或者无法从一个进程创建两个共享内存。

【问题讨论】:

【参考方案1】:

您可能对共享内存段使用相同的密钥 - 如果您想要多个共享内存段,那么您需要使用不同的密钥。有关获取密钥的标准方法,请参见 ftok 的手册页。

存在系统级别限制以防止使用过多内存 - kernel.shmmax 和相关的 sysctl 属性。

这是一个非常简单的示例应用程序,它完全按照问题的要求:

#include <sys/shm.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>

int main(int argc, char **argv) 
     key_t key1;
     key_t key2;
     if (-1 != open("/tmp/foo", O_CREAT, 0777)) 
        key1 = ftok("/tmp/foo", 0);
      else 
        perror("open");
        exit(1);
    
    if (-1 != open("/tmp/foo2", O_CREAT, 0777)) 
        key2 = ftok("/tmp/foo2", 0);
     else 
        perror("open");
        exit(1);
    
    printf("%x %x\n", key1, key2);
    int id1 = shmget(key1, 0x1000, IPC_CREAT | SHM_R | SHM_W);
    int id2 = shmget(key2, 0x2000, IPC_CREAT | SHM_R | SHM_W);
    printf("%x %x\n", id1, id2);
    void *addr1 = shmat(id1, 0, 0);
    if (addr1 == (void *)-1) perror("shmat1");
    void *addr2 = shmat(id2, 0, 0);
    if (addr2 == (void *)-1) perror("shmat2");
    printf("%p %p\n", addr1, addr2);
    shmctl(id1, IPC_RMID, NULL);
    shmctl(id2, IPC_RMID, NULL);

【讨论】:

感谢您的回复,但我可以看到 2 与 ipcs 共享内存段。共享内存 id 是 0 和一个大于 /proc/sys/kernel/shmmni (4096) 的数字。我不知道为什么第二个共享内存的数字大于 4096,即使在创建了两个段之后,它也会为两个段返回相同的 id,即 0 是第一个段的 ID。顺便说一下,共享内存的要求比 shmmax 和 shmall 低很多。 当你创建/访问一个共享内存段时,第一个参数是一个键。如果您对键使用相同的值,那么您将访问相同的共享内存段。 ID 与段数的限制无关 - 它用于并发段数。使用 ftok 的原因是它允许基于现有文件的密钥的唯一规范 - 原始算法使用 inode 号作为密钥的种子。 是的,Petesh,我为两个共享内存配置使用了两个单独的键,因为对 shmget 的调用都创建了不同的共享内存段,但返回了相同的 id。 对不起,我发现了问题并纠正了。感谢您的宝贵时间和帮助。

以上是关于从一个进程创建多个共享内存的主要内容,如果未能解决你的问题,请参考以下文章

共享内存主/从进程访问单个串口

进程通信之内存共享篇

从共享内存同时读取是不是安全?

Linux 进程通信(共享内存区)

操作系统基础知识总结

Linux 进程间通信 共享内存