общая память не распределяется между процессами - PullRequest
0 голосов
/ 09 октября 2010

Я пишу серверную программу, где она получает сообщение от клиента и широковещательное сообщение всем предыдущим клиентам. Мне нужно создать общую память между процессами, но похоже, что общая память не работает.

Вот мой код:

 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) ;

Кто-нибудь может мне помочь в этом? Большое спасибо!

Ответы [ 2 ]

1 голос
/ 09 октября 2010

Когда вы присваиваете 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 голосов
/ 15 октября 2010

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

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

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

...