2010-10-09 180 views
0

我正在寫一個服務器程序,它從客戶端接收消息並向所有以前的客戶端廣播消息。我需要在進程之間創建共享內存,但似乎共享內存不起作用。進程之間不共享共享內存

這裏是我的代碼:

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

回答

1

當你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

0

總結: 如果您使用字符串類,您將總是操作共享內存的副本。

兩個解決方案: 1.不要使用字符串,但C標準的方法來直接操作字符數組(strcat的例如追加字符) 2.一旦你完成修改您的name_list中,回到複製到共享記憶。

版本1更快。版本2更簡單。