Comment obtenir un object partagé dans une mémoire partagée

Notre application dépend d’une configuration externe fournie par une tierce partie (y compris des fonctions personnalisées de conduite / prise de décision) pouvant être chargée en tant que fichier .so.

Indépendamment, il coopère avec des modules CGI externes en utilisant un bloc de mémoire partagée, dans lequel la quasi-totalité de son état volatile est conservé, afin que les modules externes puissent le lire et le modifier le cas échéant.

Le problème est que les modules CGI requièrent également une grande quantité de données de configuration permanentes du .so, et que l’application principale effectue de nombreuses copies superflues entre les deux zones de mémoire pour rendre les données disponibles. L’idée est de charger l’ensemble de l’object partagé dans sa mémoire partagée et de le mettre directement à la disposition du CGI. Le problème est: comment?

  • dlopen et dlsym ne fournissent aucune fonctionnalité permettant d’atsortingbuer où charger le fichier SO.
  • nous avons essayé shmat (). Cela semble fonctionner uniquement jusqu’à ce qu’un CGI externe tente réellement d’accéder à la mémoire partagée. Ensuite, la zone indiquée apparaît aussi privée que si elle n’avait jamais été partagée. Peut-être que nous faisons quelque chose de mal?
  • charger le .so dans chaque script qui en a besoin est hors de question. La taille même de la structure, liée à la fréquence des appels (certains scripts sont appelés une fois par seconde pour générer des mises à jour en direct), et comme il s’agit d’une application intégrée, il est impossible d’y aller.
  • simplement memcpy () ‘insérer le .so dans shm n’est pas bon non plus – certaines structures et toutes les fonctions sont interconnectées par des pointeurs.

Je suppose que l’option la plus simple serait d’utiliser un fichier mappé en mémoire, ce que Neil a déjà proposé. Si cette option ne se remplit pas bien, vous pouvez également définir un allocateur dédié. Voici un bon article à ce sujet: Création de conteneurs STL dans la mémoire partagée

Il existe également une excellente bibliothèque Boost.Interprocess de Ion Gaztañaga avec shared_memory_object et des fonctionnalités associées. Ion a proposé la solution au comité de normalisation C ++ pour les futurs TR: fichiers mappés en mémoire et mémoire partagée pour C ++, ce qui peut indiquer qu’il vaut la peine d’envisager une solution.

La première chose à garder à l’esprit lorsque vous utilisez la mémoire partagée est que la même mémoire physique peut très bien être mappée dans l’espace d’adressage virtuel des deux processus en tant qu’adresses différentes. Cela signifie que si des pointeurs sont utilisés n’importe où dans vos structures de données, ils vont poser des problèmes. Tout doit fonctionner sur un index ou un offset pour fonctionner correctement. Pour utiliser la mémoire partagée, vous devrez purger tous les pointeurs de votre code.

Lors du chargement d’un fichier .so, une seule copie du code du fichier .so est chargée (d’où le terme object partagé).

fork peut aussi être votre ami ici. La plupart des systèmes d’exploitation modernes implémentent une sémantique de copie sur écriture. Cela signifie que lorsque vous fork , vos segments de données ne sont copiés dans la mémoire physique distincte que lorsqu’un processus écrit sur le segment de données donné.

Il est très difficile de placer des objects C ++ réels dans la mémoire partagée, comme vous l’avez constaté. Je vous recommande vivement de ne pas suivre ce chemin: placer des données à partager dans la mémoire partagée ou dans un fichier mappé en mémoire est beaucoup plus simple et susceptible d’être beaucoup plus robuste.

Vous devez implémenter la sérialisation La fonction de sérialisation de l’object convertit votre object en octets, vous pouvez ensuite écrire des octets dans SharedMemory et demander à votre module CGI de désérialiser les octets.