8
votes

Instanciation d'objets dans la mémoire partagée C ++

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

  • Tous les éléments de données (types de données standard et objets) déclarés globalement doivent être visibles à tous les appelants indépendamment du fil dans lequel le code est en cours d'exécution.
  • Tous les éléments de données déclarés localement dans une fonction ne sont visibles que dans cette fonction.
  • Tout type de données standard ou une instance de toute classe peut apparaître localement ou globalement ou les deux.

    Une solution consiste à mettre 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 programmes ultérieurs obtiendraient l'adresse de la mémoire partagée et l'utiliseraient comme un pointeur sur la structure de données globale. Les instances d'objet déclaré globalement devraient être allouées de manière dynamique dans la mémoire partagée, tandis que les instances d'objet déclarées localement pouvaient être placées sur la pile ou dans le tas local du fil de l'appelant. Les problèmes se posent parce que les objets initialisés de la mémoire globale peuvent créer et indiquer des sous-objets qui allouent (nouveau) mémoire supplémentaire. Ces nouvelles allocations doivent également être dans la mémoire partagée et vue par tous les appelants de la bibliothèque. Une autre complication est ces objets, qui contiennent des chaînes, des fichiers, etc., peuvent également être utilisés dans le programme d'appel. Lorsque déclaré dans le programme d'appel, la mémoire de l'objet est locale au programme d'appel, non partagée. Le code de l'objet doit donc gérer les deux cas. Il nous semble que la solution exigera que nous remplacons les nouveaux opérateurs de placement global de placement et de suppression réguliers. Nous avons trouvé une conception pour un système de gestion de la mémoire qui semble fonctionnera, mais nous n'avons pas trouvé d'implémentations réelles. Si quelqu'un connaît une mise en œuvre de la conception de la gestion de la mémoire de Nathan Myers ( http: // www. cantrip.org/wave12.html?seeniepage=1 ) J'apprécierais un lien avec ça. Sinon, si quelqu'un connaît un autre gestionnaire de mémoire partagé qui accueille des objets alloués de manière dynamique, j'aimerais aussi savoir à ce sujet. J'ai vérifié les bibliothèques de 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 à écrire un nous-mêmes. Étant donné que la performance et la robustesse sont importantes, il serait agréable d'utiliser le code éprouvé. Merci d'avance pour toutes les idées / aides.

    Merci pour les suggestions sur les bibliothèques ATL et OSSP. Je les vérifie maintenant bien que j'ai bien peur que ATL soit trop WinCentric si cela est cible se révèle être unix.

    Une autre chose me semble maintenant clair pour nous. Les objets peuvent être créés de manière dynamique lors de l'exécution, le schéma de gestion de la mémoire doit pouvoir attribuer des pages supplémentaires de mémoire partagée. Cela commence maintenant à ressembler à un gestionnaire de mémoire de remplacement de tas de tas rempli.


3 commentaires

La solution canonique n'est-elle pas un problème pour créer un serveur, quelles applications client peuvent utiliser? Beaucoup plus facile que le fitzing avec la mémoire partagée, qui est peu susceptible de travailler pour les raisons que vous donnez.


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


Écrire votre propre gestionnaire de tas est le chemin de la folie. Chaque fois que je suis sur un projet où les gens disent "nous ne pouvons pas le faire", où "ça" est la solution évidemment correcte, ils ont été prouvés. Je ne suis pas un fan particulier de M. Obama, mais dans ce cas, il a raison.


4 Réponses :


0
votes

OssP MM - Allocation de mémoire partagée:

homme 3 mm


0 commentaires

1
votes

Jetez un coup d'œil à Boost.InterProcess .


1 commentaires

Comme je l'ai mentionné dans le poteau, nous avons examiné la bibliothèque de Boost. Malheureusement, cela n'a pas accompli ce dont nous avions besoin. Cela nous conduit à des crénitions prometteuses, telles que le lien que j'ai mentionné dans le poste.



0
votes

Comme je suis sûr que vous avez trouvé, il s'agit d'un problème très complexe et très difficile à mettre en œuvre correctement. Quelques conseils de mes expériences. Tout d'abord, vous voudrez certainement synchroniser l'accès aux allocations de mémoire partagées à l'aide de sémaphores. Deuxièmement, toute modification des objets partagés par plusieurs processus doit également être protégée par des sémaphores. Enfin, vous devez penser en termes de compensations dès le début de la région de la mémoire partagée, plutôt que des valeurs de pointeur absolues, lors de la définition de vos objets et de vos structures de données (il est généralement possible que la mémoire soit mappée à une adresse différente de chaque processus connecté. , bien que vous puissiez choisir une adresse de cartographie fixe si vous en avez besoin). La partie dure est une manière robuste de manière robuste. Il est facile pour les structures de données basées sur la mémoire partagées pour devenir corrompues si un processus doit mourir de manière inattendue, donc un mécanisme de nettoyage / de récupération est généralement requis.


1 commentaires

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



0
votes

Étudiez également des mutiles et des sémaphores. Lorsque deux ou plusieurs entités doivent partager la mémoire ou des données, il doit exister un mécanisme de «signal de trafic» pour limiter l'accès à l'écriture à un seul utilisateur.


2 commentaires

Merci. Nous comprenons que cela doit être en sécurité et avoir mis en œuvre des mutiles pour contrôler l'accès. Le principal problème que nous avons est de savoir comment s'assurer que certains objets sont attribués dans la mémoire partagée, ainsi que tous les objets qu'ils instancient, tandis que d'autres instances des mêmes objets sont attribuées localement.


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