2010-10-09 3 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 в процессе детей, кажется, что эта модификация не рассматривается другими процессами. Может ли кто-нибудь дать какие-либо предложения? Благодаря!!

UPDATE: Я попытался изменить это, как было предложено, но все еще не работает.

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

Любой может мне помочь? Большое спасибо!

+1

1: исправьте углубление, его трудно прочитать. 2: как вы «изменяете имя_лист»? изменить указанную им память или изменить переменную? BTW, пожалуйста, включите объявления переменных – Javier

+0

исправлено. У вас есть идеи, почему это не работает? – QiLi

ответ

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

+0

Я тоже думал. @Qii: 'name_list = (char *) shm2;' создает строку. В конструкторе строк она копирует данные.Поэтому, когда вы меняете имя_листа, он меняет переменную, которая не имеет ничего общего с символом char *, который вы создали объектным способом (еще раз, потому что его скопировали). Чтобы упростить задачу, я предлагаю не использовать объекты и использовать необработанные данные (ints, chars, float и массивы и простые структуры) – 2010-10-09 02:46:45

+0

Спасибо Commodore и acidzombie24! Я часами пытался выяснить, что пошло не так. Теперь это большое облегчение. – QiLi

0

Подводя итог: Если вы используете класс string, вы всегда будете манипулировать копией разделяемой памяти.

Два решения: 1. Не используйте строку, но стандартный метод C непосредственно манипулировать массив символов (strcat, например, для добавления символов) 2. После того, как вы закончили модифицируя NAME_LIST, скопируйте его обратно в общем Память.

Версия 1 работает быстрее. Версия 2 проще.