2010-10-09 7 views
0

J'écris un programme serveur où il reçoit un message du client et un message diffusé à tous les clients précédents. J'ai besoin de créer une mémoire partagée entre les processus, mais il semble que la mémoire partagée ne fonctionne pas.La mémoire partagée n'est pas partagée entre les processus

Voici mon code:

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

Lorsque je modifie liste_noms dans le processus d'enfants, il semble que cette modification ne se voit pas par d'autres procédés. Quelqu'un peut-il donner des suggestions? Merci!! MISE À JOUR: J'ai essayé de changer à ceci comme suggéré, mais ne fonctionne toujours pas.

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

Quelqu'un peut-il m'aider? Merci beaucoup!

+1

1: s'il vous plaît corriger l'indentation, il est difficile de lire votre code. 2: comment modifiez-vous name_list? modifier la mémoire pointée par elle, ou modifier la variable? BTW, s'il vous plaît inclure les déclarations variables – Javier

+0

fixe. Avez-vous une idée pourquoi cela ne marche pas? – QiLi

Répondre

1

Lorsque vous attribuez l'objet std::stringname_list au pointeur que vous obtenez de la mémoire partagée:

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

vous appelez l'opérateur d'affectation de la chaîne, qui copies le pointeur, il est donné dans une nouvelle mémoire. Lorsque votre code manipule name_list, il manipule la copie , laissant la mémoire partagée intacte.

Il semble que vous essayez d'écrire dans la mémoire partagée à partir d'un processus, et de lire dans un autre processus, ce qui n'est pas un problème trivial à résoudre. Déterminer quel processus peut lire et écrire quelles parties de la mémoire sont difficiles, tout comme la cohérence du cache. Recherchez les tampons d'anneau circulaire producteur-consommateur (soit sur Google ou ici sur Stack Overflow) pour trouver des solutions standard à ce problème.

Pour répondre à votre question initiale, une fois que vous avez manipulé la chaîne dans la mémoire locale, vous devez la remettre en mémoire partagée. Cela fera dans un pincement:

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

Vous pouvez également manipuler directement la mémoire partagée, en utilisant le pointeur shm2, en utilisant des pointeurs C directement, en prenant soin de ne pas déborder le tampon 1000 octets.

+0

Salut Commodore, votre réponse semble être proche de la solution. Excusez-moi si je suis stupide ici, mais je ne comprends toujours pas pourquoi je laisse la mémoire partagée intacte. Pourriez-vous s'il vous plaît expliquer plus en détail? Merci!! – QiLi

+0

Je pensais la même chose. @Qii: 'name_list = (char *) shm2;' crée une chaîne. Dans le constructeur de chaîne, il COPIE les données.Donc, quand vous changez name_list, cela change la variable qui n'a rien à voir avec le char *, vous avez construit le chemin de l'objet (encore une fois parce qu'il est copié). Pour faciliter les choses je suggère de ne pas utiliser d'objets et d'utiliser des données brutes (ints, chars, float et tableaux et structures simples) –

+0

Merci Commodore et acidzombie24! J'ai passé des heures à essayer de comprendre ce qui n'allait pas. Maintenant, c'est un grand soulagement. – QiLi

0

Pour résumer: Si vous utilisez une classe de chaînes, vous manipulerez toujours une copie de la mémoire partagée.

Deux solutions: 1. Ne pas utiliser la chaîne, mais la méthode standard C pour manipuler directement le tableau de caractères (strcat par exemple pour ajouter des caractères) 2. Une fois que vous avez fini de modifier votre liste_noms, copiez-le revenir à la commune Mémoire.

La version 1 est plus rapide. La version 2 est plus simple.

Questions connexes