进程之间不共享共享内存

问题描述:

我正在写一个服务器程序,它从客户端接收消息并向所有以前的客户端广播消息。我需要在进程之间创建共享内存,但似乎共享内存不起作用。进程之间不共享共享内存

这里是我的代码:

int shmid2; key_t key2; void* shm2; 
string name_list; 
key2=ftok("tmp",'d'); 
//create 
if ((shmid2 = shmget (key2, sizeof(char)*1000, IPC_CREAT | 0666)) < 0) { 
     perror("shmget2"); 
     exit(1);} 
//attach 
shm2 = shmat(shmid2, (void *)0, 0) ; 
name_list= (char*) shm2; 
if (shm2 == (char *) -1) { 
     perror("shmat2"); 
     exit(1);} 
... do other things... 
    switch (pid=fork()){ 
    case -1: 
    { perror("ERROR on fork"); 
    break;} 
    case 0://children 
    { 
    ...modify name_list by getting message and append message to name_list.. 
    name_list.append(message); 
    break;} 
    default://parent 
    close(connection); 
    } 

当我修改孩子的过程name_list中,似乎这种修改不被其他进程可见。 任何人都可以提出任何建议吗?谢谢!!

更新:我试图改变这个建议,但仍然无法正常工作。

name_list = (char*) shmat(shmid2, (void *)0, 0) ; 

任何人都可以帮助我吗?非常感谢!

+1

1:请修复缩进,很难读取您的代码。 2:你如何修改name_list?修改它指向的内存,或修改变量?顺便说一句,请包括固定的变量声明 – Javier 2010-10-09 01:22:28

+0

。你有什么想法,为什么这不起作用? – QiLi 2010-10-09 01:38:44

当你std::string对象name_list分配给您共享内存得到的指针:

string name_list; 
// ... 
shm2 = shmat(shmid2, (void *)0, 0) ; 
name_list= (char*) shm2; 
// ... 
name_list.append(message); 

你调用该字符串的赋值操作符,这副本指针它给到新的内存。当您的代码操作name_list时,它将操纵副本,从而不改变共享内存。

看起来你试图从一个进程写入共享内存,并在另一个进程中读取它,这并不是一个小问题。确定哪个进程可以读写哪些内存很棘手,就像保持高速缓存一致性一样。查找生产者 - 消费者的环形缓冲区(在Google上或在Stack Overflow上)以获得针对此问题的一些标准解决方案。

要回答你原来的问题,一旦你操纵了本地内存中的字符串,你需要把它放回共享内存。这将做在紧要关头:

if(name_list.size() <= 1000) { 
    memcpy(shm2, name_list.data(), name_list.size()); 
} else { 
    // error: name list overflowed shared memory 
} 

你也可以直接操纵共享内存,使用指针shm2,直接使用C指针,注意不要溢出的1000个字节的缓冲区。

+0

嗨Commodore,你的答案似乎接近解决方案。对不起,如果我在这里很愚蠢,但我仍然不明白为什么我不会改变共享记忆。你能详细解释一下吗?谢谢!! – QiLi 2010-10-09 02:36:48

+0

我在想同样的事情。 @Qii:'name_list =(char *)shm2;'创建一个字符串。在字符串构造函数中,它复制数据。所以当你改变name_list时,它会改变与你构造对象方式的char *无关的变量(再次因为它被复制)。为了方便起见,我建议不要使用对象并使用原始数据(整数,字符,浮点数组和简单结构) – 2010-10-09 02:46:45

+0

感谢Commodore和acidzombie24!我花了数小时试图弄清楚出了什么问题。现在这是一个很大的安慰。 – QiLi 2010-10-09 03:01:38

总结: 如果您使用字符串类,您将总是操作共享内存的副本。

两个解决方案: 1.不要使用字符串,但C标准的方法来直接操作字符数组(strcat的例如追加字符) 2.一旦你完成修改您的name_list中,回到复制到共享记忆。

版本1更快。版本2更简单。