web-dev-qa-db-fra.com

Comment partager de la mémoire entre des applications écrites en C / C ++

Je passe par un programme écrit en C/C++ pour le contrôle en robotique. Fondamentalement, trois programmes différents s'exécutent en même temps et communiquent via la mémoire partagée. Sur Google, j'ai trouvé des idées comme vxWorks et les en-têtes interprocessus des bibliothèques boost ( documentation Boost: partage de mémoire entre les processus ).

Maintenant, je ne veux pas regarder l'implémentation, je peux lire le lien ci-dessus. Mais je n'arrive pas à comprendre comment la bibliothèque de boost fait cela. Je veux dire, une application alloue de la mémoire et d'autres accèdent à cette mémoire, mais comment communiquent-ils? n'est-il pas dangereux de le faire?

9
cauchy

Mais je n'arrive pas à comprendre comment la bibliothèque de boost fait cela.

Le mécanisme interprocessus boost a trois composants nécessaires pour fonctionner:

  1. fichier mappé en mémoire: un fichier mappé en mémoire doit être créé et transmis à un allocateur boost.interprocess. Cet allocateur prendra des morceaux du fichier et les utilisera comme s'ils étaient retournés par un allocateur std ::, avec un mappage appliqué afin que la mémoire soit compatible avec la mémoire spécifique en cours de traitement.

  2. boost.interprocess container; ce type de conteneur utilisera la mémoire retournée par l'allocateur et offrira une interface de type std :: container (begin/end/size/Push_back, etc.).

  3. mécanisme de synchronisation; cela peut être n'importe quel mutex interprocessus et doit être utilisé pour empêcher les conditions de concurrence d'accès aux données.

Je veux dire, une application alloue de la mémoire et d'autres accèdent à cette mémoire, mais comment communiquent-ils? n'est-il pas dangereux de le faire?

La mémoire allouée est en fait un fichier mappé en mémoire partagée La communication est indirecte, les deux applications définissant ou lisant les données selon leurs besoins. La sécurité vient de l'utilisation de primitives de synchronisation interprocessus.

11
utnapistim

la mémoire partagée n'est pas l'image complète de l'IPC, c'est un mécanisme de transmission de données, mais vous avez toujours besoin d'un moyen d'informer l'autre processus que certaines données ont été mises à jour et sont disponibles pour être lues. La façon dont vous faites cela dépend de vous, généralement vous utiliseriez un mutex de système d'exploitation ou un objet événement, chaque processus attend que cela soit défini, l'écriture d'application le définit une fois son écriture terminée. Ensuite, les threads des autres programmes se réveillent et lisent.

Alternativement, vous pouvez interroger, lire les données régulièrement pour une valeur qui change lorsque les données sont mises à jour (par exemple un compteur d'incrémentation).

5
gbjbaanb

Boost utilise le mappage de la mémoire d'un fichier.

Unix et Windows prennent en charge la création de fichiers qui n'existent pas sur le système de fichiers normal à cette fin.

Ensuite, vous devrez synchroniser l'accès à cette mémoire comme vous le feriez si différents threads devaient y accéder. Cela signifie que les lectures simultanées peuvent se produire sans synchronisation, mais dès qu'un processus souhaite écrire, vous devez empêcher les autres d'y accéder.

Les opérations atomiques sur la mémoire partagée sont toujours possibles si vous souhaitez une synchronisation sans verrouillage.

4
ratchet freak

Notez que C et C++ sont des langages différents.

La mémoire partagée est impossible en purement standard C11, ou C++ 11 (puisque le standard ne le définit pas), ou même C + +14 (dont n369 draft, et probablement standard officiel, ne mentionne pas la mémoire partagée en dehors du multi-threading). Vous avez donc besoin de bibliothèques supplémentaires pour obtenir la mémoire partagée. Mais certains systèmes d'exploitation prennent en charge la mémoire partagée. Il existe donc plusieurs bibliothèques fournissant une mémoire partagée, construites au-dessus des services du système d'exploitation existants. Vous pourriez peut-être envisager d'utiliser la bibliothèque de framework POCO (qui résume les détails spécifiques au système d'exploitation)

Pour Linux (et peut-être POSIX), regardez dans shm_overview (7) . Vous devrez synchroniser, alors voyez aussi sem_overview (7)

VXWorks (que je ne connais pas, mais googlé pour cela) a VxMP

Vous devez bien comprendre ce qui se passe réellement. Vous voulez probablement partager uniquement les anciennes données simples struct- s (pas les classes C++!) Et vous devez faire très attention aux adresses (chaque processus peut obtenir une adresse différente pour le segment de mémoire partagée) et à propos de la synchronisation.

Vous pouvez également utiliser des threads. Notez que la norme C++ 11 définit un bibliothèque de threads .

3

La mémoire partagée n'est encore que de la mémoire. Vous pouvez y placer un mutex, un verrou tournant ou toute autre primitive de synchronisation et les utiliser pour synchroniser l'accès de vos processus à la mémoire partagée, exactement comme les threads utilisent ces primitives pour synchroniser l'accès à la mémoire qui leur est visible.

Les seules vraies différences sont:

  1. les threads partagent toute la mémoire et le même espace d'adressage, donc les pointeurs bruts fonctionnent pour eux. La mémoire partagée entre les processus fonctionne exactement de la même manière, mais peut être mappée à différentes adresses dans chaque processus, vous ne pouvez donc pas simplement passer des pointeurs bruts entre eux

    • NB. cela a un effet d'entraînement sur certains détails d'implémentation des méthodes virtuelles, des informations sur le type d'exécution et certains autres mécanismes C++. Restez fidèle aux types trivialement initialisables (données anciennes simples) sans méthodes virtuelles ou transtypages dynamiques dans votre mémoire partagée, n'utilisez pas de typeid sur eux, et ça devrait aller.
  2. certaines primitives de synchronisation peuvent avoir besoin d'indicateurs ou d'attributs spéciaux pour fonctionner correctement entre les processus (voir PTHREAD_PROCESS_SHARED attribut pour les mutex de thread POSIX, par exemple). Cela ne concerne pas vraiment la mémoire et la synchronisation en soi, mais en raison de l'interaction noyau/ordonnanceur nécessaire pour réveiller les serveurs endormis.


Donc:

mais comment communiquent-ils?

De la même manière que différents threads communiquent, permettant les mises en garde ci-dessus

n'est-il pas dangereux de le faire?

Oui, il est tout aussi dangereux pour les processus de communiquer via la mémoire partagée que pour les threads de communiquer via la mémoire partagée, et ils ont besoin d'une synchronisation équivalente (ou identique) pour rendre sûr.

3
Useless