2009-03-30 23 views
2

J'essaie actuellement d'implémenter une communication interprocess à l'aide du mécanisme Windows CreateFileMapping. Je sais que je dois d'abord créer un objet de mappage de fichier avec CreateFileMapping, puis créer un pointeur vers les données réelles avec MapViewOfFile. L'exemple place ensuite les données dans le mapfile en utilisant CopyMemory.Utilisation de la mémoire partagée sous Windows. Comment passer des données différentes

Dans mon application, j'ai un tampon d'image (1 Mo de large) que je veux envoyer à un autre processus. Alors maintenant, je demande un pointeur sur l'image, puis copiez le tampon d'image entière dans le mapfile. Mais je me demande si c'est vraiment nécessaire. N'est-il pas possible de simplement copier un pointeur réel dans la mémoire partagée qui pointe vers les données du tampon d'image? J'ai essayé un peu mais n'ai pas réussi.

+0

Murali Devi fournit [exemple de code de travail pour la mémoire partagée sous Windows] (http://comsci.liu.edu/~murali/win32/SharedMemory.htm). Son exemple utilise de la mémoire, pas un fichier réel, donc c'est exactement le cas que vous décrivez. –

Répondre

8

Différents processus ont des espaces d'adressage différents. Si vous passez un pointeur valide dans un processus à un autre processus, il pointera probablement vers des données aléatoires dans le second processus. Donc vous devrez copier toutes les données.

+1

Pas toujours vrai. – RandomNickName42

+2

@ RandomNickName42: à l'exception de la mémoire partagée, il est généralement vrai pour tous les systèmes d'exploitation courants. – Zifre

0

Vous pouvez utiliser le regroupement de pointeurs.

8

I fortement vous recommandons d'utiliser Boost::interprocess. Il a beaucoup de trucs pour gérer ce genre de choses & inclut même certaines fonctions spéciales Windows uniquement au cas où vous avez besoin d'interopérer avec d'autres processus qui utilisent des fonctionnalités particulières de Win32.

La chose la plus importante est d'utiliser offset pointers plutôt que des pointeurs réguliers. Les pointeurs décalés sont fondamentalement des pointeurs relatifs (ils stockent la différence entre l'endroit où se trouve le pointeur et l'endroit où il pointe). Cela signifie que même si les deux pointeurs sont mappés à des espaces adresse différents, tant que les mappages sont identiques dans la structure, alors vous allez bien.

J'ai utilisé toutes sortes de structures de données compliquées avec des pointeurs intelligents décalés et cela a fonctionné comme un charme.

+0

Il s'agit de "pointeurs basés" sur a.k.a, très utiles lorsque les pointeurs 64 bits sont partout. – RandomNickName42

0

Si cela est possible, il est préférable de charger/générer directement les données d'image dans la zone de mémoire partagée. Cela élimine la copie de la mémoire et la place directement là où elle doit être. Quand il est prêt, vous pouvez signaler l'autre processus, en lui donnant le décalage dans votre mémoire partagée où les données commencent.

2

Vous CAN CAN obtenir la mémoire partagée pour utiliser le même adresse sur 2 processus pour Windows. C'est réalisable avec plusieurs techniques.

En utilisant MapViewOfFileEx, voici l'experpt significatif de MSDN.

Si une adresse de cartographie proposée est fourni, le fichier est mis en correspondance à l' adresse indiquée (arrondi au le plus proche 64K-frontière) si l'espace d'adresse assez à l'adresse spécifiée. S'il n'y a pas assez d'espace adresse, la fonction échoue.

En règle générale, l'adresse proposée est utilisée pour spécifier qu'un fichier doit être mappé à la même adresse dans plusieurs processus . Cela nécessite que la zone d'adresse soit disponible dans tous les processus impliqués .Aucune autre allocation de mémoire peut avoir lieu dans la région utilisée pour le mappage, , y compris l'utilisation de la fonction VirtualAlloc ou VirtualAllocEx pour réserver la mémoire .

Si le paramètre lpBaseAddress spécifie un décalage de base, la fonction réussit si la région mémoire spécifiée est déjà utilisé par le processus d'appel . Le système n'assure pas que la même zone de mémoire est disponible pour le fichier mappé en mémoire dans d'autres processus 32 bits.

Une autre technique connexe consiste à utiliser une DLL avec une section marquée Read + Write + Shared. Dans ce cas, le système d'exploitation fera à peu près l'appel MapViewOfFileEx pour vous et pour tout autre processus qui charge la DLL.

Vous devrez peut-être marquer votre DLL à une adresse de chargement FIXE, pas relocateable etc .. naturellement.

3

La mémoire partagée ne signifie pas l'envoi et la réception de données. C'est une mémoire créée pour le nombre de processus sans violation. Pour cela, vous devez suivre certains mécanismes comme les verrous afin que les données ne seront pas corrompues.

En cours 1:

CreateFileMapping(): Il crée le Shared bloc mémoire, avec le nom fourni dans le dernier paramètre, si elle est pas déjà présent et retourne une poignée (vous pouvez l'appeler un pointeur), si réussi.

MapViewOfFile(): Il mappe (inclut) ce bloc partagé dans l'espace d'adressage du processus et renvoie un handle (encore une fois vous pouvez dire un pointeur).

Avec ce pointeur renvoyé par MapViewOfFile() seulement vous pouvez accéder à ce bloc partagé.

En cours 2:

OpenFileMapping(): Si le bloc de mémoire partagée est créé avec succès par CreateFileMapping(), vous pouvez l'utiliser avec le même nom (nom utilisé pour créer le bloc de mémoire partagée).

UnmapViewOfFile(): Il va démapper (vous pouvez supprimer le bloc de mémoire partagée de cet espace d'adressage de processus). Lorsque vous avez fini d'utiliser la mémoire partagée (c'est-à-dire, accès, modification, etc.), appelez cette fonction.

Closehandle(): enfin de détacher le bloc de mémoire partagée du processus, appelez ceci avec argument, handle retourné par OpenFileMapping() ou CreateFileMapping().

Bien que ces fonctions semblent simples, le comportement est difficile si les indicateurs ne sont pas sélectionnés correctement. Si vous souhaitez lire ou écrire de la mémoire partagée, spécifiez PAGE_EXECUTE_READWRITE dans CreateFileMapping().

Chaque fois que vous souhaitez accéder à la mémoire partagée après l'avoir créée avec succès, utilisez FILE_MAP_ALL_ACCESS dans MapViewOfFile().

Il est préférable de spécifier FALSE (ne pas hériter du handle du processus parent) dans OpenFileMapping() car cela évitera toute confusion.