none
mapping memoire d'une application RRS feed

  • Question

  • Bonjour,

    Existe-il une option, astuce, ... permettant, au link, de reserver une zone memoire dans l'espace memoire d'une application afin de prevoir une zone pour du sharing-memory (file mapping) ?

    Une zone de memoire partagee entre deux applications est-elle forcement situee a la meme adresse memoire dans l'espace memoire des deux applications ?

    Merci

    Cordialement,

    Gil
    mercredi 24 août 2011 15:40

Réponses

  • Cela me rassure que vous vous posiez les mêmes questions. ;-)

    Pour 1/ je suis toujours très dubitatif sur cette contrainte, et faire un argumentaire soit, mais il fait être absolument sûr que ce n'est pas une mécompréhension. Sinon, Internet regorge d'astuce pour caché ces problématique d'adresse de mapping différente de la mémoire partagé.

    Pour 2/ je peux vous donnez quelques pistes mais cela rendra votre code/configuration de compilation, au minimum, peu maintenable, au pire plantage aléatoire. Donc, à ne faire qu'en absolue nécessité.

    Pour votre 1ère question (dans votre 2/ si j'ai bien suivi, et c'est loin d'être sûr) , il faut bien comprendre que ce n'est pas le linker qui décide de l'organisation mémoire du programme mais le loader du système d'exploitation qui à toute l'attitude pour agencé la mémoire du processus comme il le souhaite. Vous pouvez toujours jouer au bras de faire avec le loader, mais cela ne passera que par du code et très vraisemblablement avec des instructions réservées au Ring0 (Drivers). La piste que je mentionne au paragraphe précédent est que vous pouvez indiquer une zone mémoire réservé de manière très très indirecte. Ceci est bien sûr purement hypothétique et non testé.

    Vous pouvez spécifier une adresse favorite pour le chargement d'une dll et interdire que cette dll soit déplacé en cas de collision (une dll psychorigide quoi ;-).

    C'est l'option du linker "/BASE" qui spécifie l'adresse favorite de la dll.

    C'est l'option du linker "/FIXED" qui spécifie que la dll ne doit pas bouger.

    Voir MSDN

    http://msdn.microsoft.com/en-us/library/y0zzbyt4(v=VS.100).aspx

    Il faut ensuite trouver un moyen pour générer une section de code pour cette dll d'une longueur approximativement égale à la taille de la zone partagée recherchée.

    Si vous liez statiquement vos programmes avec une telle dll, cette zone sera donc "réservée". Si le loader se retrouve avec deux dll psychorigide au même endroit, le programme ne démarre même pas.

    Il reste après contourner les éventuelles protections de l'OS qui pourrait interdire l'écriture sur une section de code. Bon courage.

    Et réflexion faite, avec le simple mécanisme de section de données partagées des Dll intégré à Windows, implémenter une dll qui servirait de monitoring d'accès à une zone partagé entre plusieurs programmes est très simple à faire. Donc si c'est vraiment une limitation de votre solution DDS et que cotre fournisseur n'est pas foutu de vous donner une solution sans cette limitations, c'est que c'est vraiment des guignols.

    Je pourrais toujours leur faire une formation sur le b.a.-ba de la programmation sous Windows. ;-)


    Paul Bacelar, Ex - MVP VC++
    jeudi 25 août 2011 18:31
    Modérateur
  • L'utilisation d'une librairie de ressource uniquement (http://msdn.microsoft.com/fr-fr/library/24b2tcy0.aspx) pourrait simplifier le process car :

    - très vraisemblablement, ce type de dll dispose d'une seule section et c'est assez facile d'agrandir ou de diminuer ce type de Dll.

    - pour des problèmes de compatibilité Win95, les pages mémoire ce type de dll ne devraient pas être protégées en écriture.


    Paul Bacelar, Ex - MVP VC++
    vendredi 26 août 2011 12:52
    Modérateur

Toutes les réponses

  • "Une zone de memoire partagee entre deux applications est-elle forcement situee a la meme adresse memoire dans l'espace memoire des deux applications ?"

    Non, une zone de mémoire partagée a très peu de chance d'être mappée aux mêmes adresses dans 2 processus différents.

    Il ne faut pas utiliser de pointeurs sur des données dans cette zone, même s'ils sont stockés dans cette même zone. Utilisez à la rigueur des offsets pour avoir des adresses relatives au début de la zone mappée.

    C'est peut-être possible de piloter l'éditeur de lien pour réserver des zones mémoires mais je ne vous le conseil pas. Beaucoup des dispositifs de sécurisation des applications "offusquent" le mapping mémoire.

    Je vous conseil plutôt d'accéder aux données partagées par une arithmétique de pointeur qui prend comme base le début de la zone mappée. Vous n'auriez donc pas besoin de réserver à l'avance une plage d'adresse.

    Concrètement, pourquoi avez-vous besoin d'une zone mappée partagée (Hook système, anti-virus, rootkit ;-), communication inter-process (pas bien ça)) ?

    En ayant des lumières sur le but, on pourrait vous donner un moyen plus simple que le mapping mémoire partagée, solution des plus "bas niveau" (mais pas vil ;-) ).


    Paul Bacelar, Ex - MVP VC++


    • Proposé comme réponse Ciprian Duduiala jeudi 25 août 2011 06:44
    • Non proposé comme réponse gil[78fr] jeudi 25 août 2011 07:31
    mercredi 24 août 2011 16:22
    Modérateur
  • Bonjour Paul,

     

    Merci pour votre réponse.

    Je suis étonné  que vous associez un usage de shared memory à du "pas bien ça"; je fais effectivement de la com. interprocess et ce serait plutôt du "obligé ça" :-)

    J'utilise une solution DDS (middleware) pour des systèmes embarqués qui m'impose de passer par du shared memory et je constate par l'usage de vmmap que la zone de shared memory en question est localisée à une adresse unifiée dans toutes mes applications. Peut être est-ce actuellement imposé par ma solution DDS; je vais creuser cela avec un p'tit programme de test selon les exemples du MSDN et je vous en dirai plus alors.

    L'autre point de ma question, celui qui m'intéresse en particulier, est celui concernant la capacité d'indiquer au link de réserver une zone mémoire libre dans l'espace virtuel de l'application à générer.

     

    Merci encore

    Gil

     

     

    jeudi 25 août 2011 07:31
  • Je viens de lister toutes les options du linker est je n'ai pas vu d'option correspondante à un freez d'une plage mémoire.

    Mais cela ne m'étonne pas car le mapping mémoire de chaque programme est extrêmement différent et varie d'une machine à une autre.

    Je n'ai qu'une expérience WinCE de l'embarqué et je n'y ai vue que les mêmes contraintes.

    je ne connais pas de solution DDS mais il semble qu'elles contiennent un paradigme Publisher/Subscriber difficilement compatible avec un simple partage mémoire.

    L'approche habituelle est de faire un mapping mémoire est d'utiliser les mécanismes standards du langage pour faire des références relatives au début de la zone mémoire partagée.

    Avec cela, le fait que chaque programme mappe cette mémoire dans des zones différentes ne pose pas de problème particulier.

    Initialiser un pointeur de tableau d'octet à la valeur retournée par la fonction MapViewOfFile permet d'accéder sans problème à cette zone, même si chaque programme dispose d'une valeur différente et que cette adresse change à chaque démarrage. J'ai donc du mal à comprendre pourquoi vous avez besoin d'avoir une plage d'adresse réservée pour ça.

    La communication inter-process per mémoire partagé brute pose de gros problème de partage d'un meta modèle et de la concurrence d'accès.

    Les plateformes modernes disposent d'un nombre impressionnant de mécanisme de communication inter-process (pipe, socket, mailslot, file de message, ...) que revenir à de la mémoire partagée ne me semble justifié que pour des hook systèmes.

    Donc, pourquoi ne pas utiliser l'un de ces mécanismes bien moins contraignant que la mémoire partagée ?


    Paul Bacelar, Ex - MVP VC++
    jeudi 25 août 2011 09:04
    Modérateur
  • Je ne développe pas une solution DDS, j'en utilise une qui fonctionne au travers de shared-memory, je n'ai donc pas le choix sur la solution de communication à employer.

    D'ailleurs, je ne suis pas loin de parier que la majorité (sinon toutes) des implémentation de DDS utilisent de la memoire partagée pour des raisons de performances.

    Le paradigme Publisher/Suscriber etant une vision de plus haut niveau que le choix d'implémentation de communication sur la cible; il dépend du réseau de communication inter-process à mettre en oeuvre.

    Typiquement dans mon cas:

    - shared-memory pour de la com. inter-process sur une même machine

    - UDP/TCP/IP pour de la com. inter-machine.

    Effectivement il existe de nombreuses manières de faire de la communication inter-process; le shared-memory etant l'un des plus efficaces en communication locale, c'est celui qui est utilisé dans la solution que j'utilise.

    Ce que je constate aujourd'hui c'est que la zone de mémoire partagée utilisée par mon middleware semble devoir se situer au même emplacement mémoire dans toutes mes applications (environ 50) en cours de dév. et c'est une contrainte conséquente.

     

    Merci

    Gil

    jeudi 25 août 2011 09:23
  • Franchement, je ne pense pas qu'une implémentation pérenne de DDS sous Windows demande cette contrainte.

    S'il y a ce type de contrainte, je pense qu'elle doit être induite pas les données stockées dans DDS.

    Vous ne devriez pas utiliser de pointeurs ou de types spécifiques à un langage ou influencés par les options de compilation dans les données à stocker dans DDS.

    En respectant ces contraintes, je comprend pas pourquoi les adresses de mapping doivent être identiques.

    Pouvez-vous nous donnez les références de l'implémentation DDS mentionnant cette contrainte, car je penche plus pour une mauvaise compréhension que pour une limitation.


    Paul Bacelar, Ex - MVP VC++
    jeudi 25 août 2011 11:58
    Modérateur
  • Je me pose les mêmes questions que vous; je pense aussi que cette contrainte est étonnante et j'ai besoin de deux choses:

    1/ de monter un argumentaire pour plaider le pb auprès de mon fournisseur de solution afin qu'il voit comment changer cet état de fait dans son produit.

    2/ voir les solutions de contournement possibles en attendant une résolution de mon pb afin que mon projet ne se retrouve pas à l'arrêt.

    ma 1ère question était dans l'objectif de répondre au point 2. J'entends que de votre avis il n'y a pas moyen de "forcer" une organisation particulière de la mémoire lors de la génération.

    ma 2° question est dans l'objectif du point 1: aller vers mon fournisseur en lui demandant comment (puisque ce n'est pas une contrainte Windows) il se fait que son produit impose une telle contrainte.

     

    Merci

    Gil

    jeudi 25 août 2011 12:08
  • Cela me rassure que vous vous posiez les mêmes questions. ;-)

    Pour 1/ je suis toujours très dubitatif sur cette contrainte, et faire un argumentaire soit, mais il fait être absolument sûr que ce n'est pas une mécompréhension. Sinon, Internet regorge d'astuce pour caché ces problématique d'adresse de mapping différente de la mémoire partagé.

    Pour 2/ je peux vous donnez quelques pistes mais cela rendra votre code/configuration de compilation, au minimum, peu maintenable, au pire plantage aléatoire. Donc, à ne faire qu'en absolue nécessité.

    Pour votre 1ère question (dans votre 2/ si j'ai bien suivi, et c'est loin d'être sûr) , il faut bien comprendre que ce n'est pas le linker qui décide de l'organisation mémoire du programme mais le loader du système d'exploitation qui à toute l'attitude pour agencé la mémoire du processus comme il le souhaite. Vous pouvez toujours jouer au bras de faire avec le loader, mais cela ne passera que par du code et très vraisemblablement avec des instructions réservées au Ring0 (Drivers). La piste que je mentionne au paragraphe précédent est que vous pouvez indiquer une zone mémoire réservé de manière très très indirecte. Ceci est bien sûr purement hypothétique et non testé.

    Vous pouvez spécifier une adresse favorite pour le chargement d'une dll et interdire que cette dll soit déplacé en cas de collision (une dll psychorigide quoi ;-).

    C'est l'option du linker "/BASE" qui spécifie l'adresse favorite de la dll.

    C'est l'option du linker "/FIXED" qui spécifie que la dll ne doit pas bouger.

    Voir MSDN

    http://msdn.microsoft.com/en-us/library/y0zzbyt4(v=VS.100).aspx

    Il faut ensuite trouver un moyen pour générer une section de code pour cette dll d'une longueur approximativement égale à la taille de la zone partagée recherchée.

    Si vous liez statiquement vos programmes avec une telle dll, cette zone sera donc "réservée". Si le loader se retrouve avec deux dll psychorigide au même endroit, le programme ne démarre même pas.

    Il reste après contourner les éventuelles protections de l'OS qui pourrait interdire l'écriture sur une section de code. Bon courage.

    Et réflexion faite, avec le simple mécanisme de section de données partagées des Dll intégré à Windows, implémenter une dll qui servirait de monitoring d'accès à une zone partagé entre plusieurs programmes est très simple à faire. Donc si c'est vraiment une limitation de votre solution DDS et que cotre fournisseur n'est pas foutu de vous donner une solution sans cette limitations, c'est que c'est vraiment des guignols.

    Je pourrais toujours leur faire une formation sur le b.a.-ba de la programmation sous Windows. ;-)


    Paul Bacelar, Ex - MVP VC++
    jeudi 25 août 2011 18:31
    Modérateur
  • L'utilisation d'une librairie de ressource uniquement (http://msdn.microsoft.com/fr-fr/library/24b2tcy0.aspx) pourrait simplifier le process car :

    - très vraisemblablement, ce type de dll dispose d'une seule section et c'est assez facile d'agrandir ou de diminuer ce type de Dll.

    - pour des problèmes de compatibilité Win95, les pages mémoire ce type de dll ne devraient pas être protégées en écriture.


    Paul Bacelar, Ex - MVP VC++
    vendredi 26 août 2011 12:52
    Modérateur
  • Bonjour, Gil,

    Est-ce que vous avez pu avancer en utilisant les informations fournies par Paul ? Merci de partager avec nous les résultats, afin que d'autres personnes avec le même problème puissent profiter de cette solution.

     

    Cordialement,

    Cipri


    Suivez MSDN sur Twitter   Suivez MSDN sur Facebook


    Ciprian DUDUIALA, MSFT  
    •Nous vous prions de considérer que dans le cadre de ce forum on n’offre pas de support technique et aucune garantie de la part de Microsoft ne peut être offerte.

    lundi 29 août 2011 06:25
  • Bonjour,

    J'ai mis en oeuvre un programme me permettant de tester la gestion de la mémoire partagée sous windows. J'ai donc confirmé par l'exemple les dires de Paul que je remercie encore pour son aide.

    Concernant les essais de "réservation" de mémoire par l'usage du mécanisme de section de données partagées des DLL, j'aimerais faire des essais sur ce sujet mais je n'en ai pas le temps dans l'immédiat.

    Le sujet me semble techniquement complexe et risqué, je vais donc le garder sous le coude pour l'intérêt technique qu'il représente mais je doute pouvoir le proposer comme solution alternative ?

     

    Merci encore à vous.

    Cordialement,

    Gil.

    lundi 29 août 2011 07:23
  • Je suis tout à fait d'accord avec votre analyse.

    Mais, il faut toujours commencer par les points techniquement complexes et dangereux, pour ne pas trop invertir en cas d'échecs.

    Je ne vous conseil pas de faire les tambouilles que je présente, loin de moi, mais il faut absolument que votre fournisseur de solution DDS fournisse une implémentation viable.

    Je pense que cela ne serait qu'une simple explication de l'API car je ne pense pas qu'un fournisseur sérieux puisse demander de telles contraintes.


    Paul Bacelar, Ex - MVP VC++
    lundi 29 août 2011 08:33
    Modérateur