进程之间不共享共享内存
我正在写一个服务器程序,它从客户端接收消息并向所有以前的客户端广播消息。我需要在进程之间创建共享内存,但似乎共享内存不起作用。进程之间不共享共享内存
这里是我的代码:
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) ;
任何人都可以帮助我吗?非常感谢!
当你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个字节的缓冲区。
嗨Commodore,你的答案似乎接近解决方案。对不起,如果我在这里很愚蠢,但我仍然不明白为什么我不会改变共享记忆。你能详细解释一下吗?谢谢!! – QiLi 2010-10-09 02:36:48
我在想同样的事情。 @Qii:'name_list =(char *)shm2;'创建一个字符串。在字符串构造函数中,它复制数据。所以当你改变name_list时,它会改变与你构造对象方式的char *无关的变量(再次因为它被复制)。为了方便起见,我建议不要使用对象并使用原始数据(整数,字符,浮点数组和简单结构) – 2010-10-09 02:46:45
感谢Commodore和acidzombie24!我花了数小时试图弄清楚出了什么问题。现在这是一个很大的安慰。 – QiLi 2010-10-09 03:01:38
总结: 如果您使用字符串类,您将总是操作共享内存的副本。
两个解决方案: 1.不要使用字符串,但C标准的方法来直接操作字符数组(strcat的例如追加字符) 2.一旦你完成修改您的name_list中,回到复制到共享记忆。
版本1更快。版本2更简单。
1:请修复缩进,很难读取您的代码。 2:你如何修改name_list?修改它指向的内存,或修改变量?顺便说一句,请包括固定的变量声明 – Javier 2010-10-09 01:22:28
。你有什么想法,为什么这不起作用? – QiLi 2010-10-09 01:38:44