2009-12-23 5 views
8

Nous avons besoin de plusieurs programmes pour appeler des fonctions dans une bibliothèque commune. La bibliothèque fonctionne et accède à une mémoire globale commune. Les appels de fonction de chaque programme doivent voir cette mémoire globale commune. C'est un appel de fonction a besoin de voir les mises à jour de tout appel de fonction préalable même si appelé d'un autre programme. Pour des raisons de compatibilité, nous avons plusieurs contraintes de conception sur la façon dont les fonctions exposées par la bibliothèque partagée doit fonctionner:Instanciation d'objets dans la mémoire partagée C++

  • Tous les éléments de données (les deux types de données standard et objets) qui sont déclarés globalement doivent être visibles pour tous les appelants quel que soit le thread dans lequel le code est en cours d'exécution.
  • Tous les éléments de données déclarés localement dans une fonction sont uniquement visibles dans cette fonction.
  • Tout type de données standard ou une instance de n'importe quelle classe peut apparaître localement ou globalement ou les deux.

Une solution consiste à placer la mémoire globale commune de la bibliothèque dans la mémoire partagée nommée. Le premier appel de bibliothèque créerait la mémoire partagée nommée et l'initialiserait. Les appels de programme suivants obtiendraient l'adresse de la mémoire partagée et l'utiliseraient comme un pointeur vers la structure de données globale. Les instances d'objets déclarées globalement doivent être allouées dynamiquement dans la mémoire partagée tandis que les instances d'objets déclarées localement peuvent être placées sur la pile ou dans le tas local du thread appelant. Des problèmes surviennent parce que les objets initialisés dans la mémoire globale peuvent créer et pointer vers des sous-objets qui allouent (nouvelle) de la mémoire supplémentaire. Ces nouvelles allocations doivent également être dans la mémoire partagée et être vues par tous les appelants de bibliothèque. Une autre complication est que ces objets, qui contiennent des chaînes, des fichiers, etc., peuvent également être utilisés dans le programme appelant. Lorsqu'il est déclaré dans le programme appelant, la mémoire de l'objet est locale au programme appelant, non partagée. Le code de l'objet doit donc gérer les deux cas. Il nous semble que la solution exigera que nous remplacions le placement global par de nouveaux opérateurs réguliers, nouveaux et supprimés. Nous avons trouvé une conception pour un système de gestion de la mémoire qui semble fonctionner, mais nous n'avons trouvé aucune implémentation réelle. Si quelqu'un connaît une implémentation de la gestion de la mémoire de Nathan Myers (http://www.cantrip.org/wave12.html?seenIEPage=1) j'apprécierais un lien vers celui-ci. Sinon, si quelqu'un connaît un autre gestionnaire de mémoire partagée qui permet d'allouer dynamiquement des objets, j'aimerais aussi le savoir. J'ai vérifié les bibliothèques Boost et toutes les autres sources que je peux trouver mais rien ne semble faire ce dont nous avons besoin. Nous préférons ne pas avoir à en écrire un nous-mêmes. Puisque la performance et la robustesse sont importantes, il serait bon d'utiliser du code éprouvé. Merci d'avance pour toute idée/aide.

Merci pour les suggestions sur les bibliothèques ATL et OSSP. Je les vérifie maintenant même si j'ai peur que l'ATL soit trop Wincentric si la cible s'avère être Unix.

Une autre chose nous semble maintenant claire. Étant donné que les objets peuvent être créés dynamiquement pendant l'exécution, le schéma de gestion de la mémoire doit être capable d'allouer des pages supplémentaires de mémoire partagée. Cela commence maintenant à ressembler à un gestionnaire de mémoire de remplacement de tas à part entière.

+2

La solution canonique à ce problème n'est-elle pas de créer un serveur que les applications clientes peuvent utiliser? Beaucoup plus facile que de rester avec la mémoire partagée, ce qui est peu probable pour les raisons que vous donnez. –

+0

D'accord avec Neil. – wheaties

+0

Oui. La refonte de l'application serait le moyen le plus simple de résoudre le problème. Malheureusement, en raison des contraintes de conception dues à la compatibilité avec d'autres composants, nous n'avons pas cette option. – BillC

Répondre

0

OSSP mm - allocation mémoire partagée:

homme 3 mm

1

Jetez un oeil à boost.interprocess.

+1

Comme je l'ai mentionné dans le post, nous avons regardé la bibliothèque Boost. Malheureusement, il n'a pas accompli ce dont nous avions besoin. Cela nous a conduit à quelques ressources prometteuses, comme le lien que j'ai mentionné dans le post. – BillC

0

Comme je suis sûr que vous avez trouvé, c'est un problème très complexe, et très difficile à mettre en œuvre correctement. Quelques conseils de mes expériences. Tout d'abord, vous aurez certainement besoin de synchroniser l'accès aux allocations de mémoire partagée en utilisant des sémaphores. Deuxièmement, toutes les modifications apportées aux objets partagés par plusieurs processus doivent également être protégées par des sémaphores.Enfin, vous devez penser en termes de décalages depuis le début de la région de mémoire partagée, plutôt que de valeurs de pointeur absolues, lors de la définition de vos objets et structures de données (il est généralement possible de mapper une adresse différente dans chaque processus joint) , bien que vous puissiez choisir une adresse de mapping fixe si vous en avez besoin). Tout mettre ensemble d'une manière robuste est la partie la plus difficile. Il est facile pour les structures de données basées sur la mémoire partagée d'être corrompues si un processus devait mourir de façon inattendue, donc un mécanisme de nettoyage/récupération est généralement requis.

+0

Vous avez parfaitement raison. Le problème est complexe et c'est pourquoi nous ne voulons pas avoir à écrire le code à partir de zéro. – BillC

0

Également étudier les mutex et les sémaphores. Lorsque deux ou plusieurs entités ont besoin de partager de la mémoire ou des données, il doit y avoir un mécanisme de «signalisation de trafic» pour limiter l'accès en écriture à un seul utilisateur.

+0

Merci. Nous comprenons que cela doit être thread safe et ont mis en œuvre des mutex pour contrôler l'accès. Le principal problème que nous avons est de savoir comment s'assurer que certains objets sont alloués dans la mémoire partagée, avec tous les objets qu'ils instancient, alors que d'autres instances des mêmes objets sont allouées localement. – BillC

+0

Mélanger processus local et mémoire partagée comme vous le décrivez semble généralement comme une recette pour un désastre. Définir un protocole de communication inter-processus plus formel est probablement une meilleure approche. –

Questions connexes