J'ai une question pour les plus calés d'entre vous ! J'ai un gros problème de mapping de page ! Voici l'objectif : implémenter deux tampons circulaires qui évitent la copie des données. Pour ce faire, les tampons sont projetés deux fois, l'un à la suite de l'autre, ainsi, lorsqu'un ensemble de données (par exemple une chaîne de caractère) se trouve en partie à la fin et au début du tampon, on peut y accéder avec une seule instruction de lecture (vu que lorsqu'on arrive à la fin de la première projection du tampon, on atteint le début de la seconde projection). Il y a donc une projection effectuée pour la page des descripteurs et deux projections par tampons pour projeter les mêmes pages dans des espaces mémoires contigus. Les projections sont effectuées à partir des pages d'un fichier (en passant par son descripteur). Voici le code de l'opération :
==> Structure utilisée pour gérer les deux tampons. Les éléments importants sont mInfoPage qui va contenir la page accueillant les descripteurs des tampons, mInData qui accueillera le tampon en entrée et mOutData qui accueillera le tampon en sortie. Les descripteurs sont décarés dans la classe parents :
class Communicator {
public:
/**
* Creates a new communicator. The real type of the communicator and his
* parameters are obtained from the ConfigFile::Element @arg config.
*
* @param config the ConfigFile::Element that stores the configuration.
*
* @return a new Communicator.
*/
static Communicator * Get(std::string & communicator);
virtual ~Communicator();
/**
* Sets the communicator as a server.
*/
virtual void Serve() = 0;
/**
* Accepts a new connection. The call to the first Accept() must follow a
* call to Serve().
*
* @return a Communicator to the connected peer.
*/
virtual const Communicator * const Accept() const = 0;
/**
* Sets the communicator as a client and connects it to the end point
* specified in the ConfigFile::Element used to build this Communicator.
*/
virtual void Connect() = 0;
virtual size_t Read(char *buffer, size_t size) = 0;
virtual size_t Write(const char *buffer, size_t size) = 0;
virtual void Sync() = 0;
/**
* Closes the connection with the end point.
*/
virtual void Close() = 0;
virtual char * getWriteAddr(size_t size)=0;
virtual void commitWrite()=0;
virtual char * getReadAddr(size_t size)=0;
virtual void commitRead()=0;
size_t getSize(){return mInPtrs->size;}
size_t getRemainingInSize(){return 0;}
size_t getRemainingOutSize(){return 0;}
desc_t * mInPtrs;
desc_t * mOutPtrs;
private:
};
Les descripteurs sont donc mInPtrs et mOutPtrs. Leur structure est définie ainsi :
typedef struct{
unsigned int lRdStart;
unsigned int lRdEnd;
unsigned int lWrtStart;
unsigned int lWrtEnd;
unsigned int hRdStart;
unsigned int hRdEnd;
unsigned int hWrtStart;
unsigned int hWrtEnd;
unsigned int size;
}desc_t;
CONCLUSION ET QUESTION Je n'ai pas utilisé le flag MAP_FIXED dans l'exemple, je laisse le système choisir où mapper les données en indiquant toute même l'adresse à laquelle elles DOIVENT être mappées. Le mapping s'effectue correctement, mais pas à l'adresse effectuée. En effet, l'adresse indiquée pour le tampon de sortie (qui est donc l'adresse de base du tampon + la taille du tampon, pour venir effectuer la seconde projection juste après la première) est déjà prise par la page contenant les descripteurs (mInfoPage !!). Si j'utilisais le flag MAP_FIXED, nous aurions le tampon correctement projeté deux fois en mémoire MAIS le tampon de sortie remplacerait la page des descripteurs. On a un problème similaire avec le tampon d'entrée. Ma question est donc, comment faire pour indiquer au système, avant le premier mapping, qu'il faut réserver de la place pour placer mon double tampon de manière contiguë, pour éviter le problème que je rencontre ? Comment indiquer au système qu'il faut réserver tout un "range" d'adresse pour la projection de mon tampon ? La fonction malloc va allouer un espace mémoire et des pages qui n'ont rien à voir avec mon tampon. Je n'ai rien trouver dans la doc. de la fonction mmap. Quelqu'un a-t'il une idée ?
Mélange de vieux C (exit, perror, printf, ...) de C++ archaïque ( pointeurs nus de partout) et du C++ "moderne" (throw, std::string, ...) dans une classe C++ dont la conception me semble s'approcher d'un fourre-tout inconsistant à la god-class, pour une problématique d'optimisation mémoire qui devrait être de la préoccupation de driver réseaux et donc clairement pas en C++ (à moins d'aimer le challenge de faire un driver en C++).
Ça sent clairement pas bon votre histoire.
Tout ça pour dire comme Ksass`Peuk, pourquoi réinventer une roue carrée ???
Ce que vous cherchez à faire est au niveau de la programmation système, avec des API des systèmes qui sont différents entre système (captain obvious inside).
Les bibliothèques réseaux s'occupent très bien de faire ce genre de trick.
Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
Excellente définition de ma petite démonstration quick and dirty qui vise à démontrer la faisabilité et l'efficacité d'une idée avant de se lancer dans des développements plus propre Il y a des bibliothèques réseaux qui permettent de transférer des données entre deux machines virtuelles KVM/Qemu en évitant la copie des données ? Si vous les connaissez, ça m'intéresse vraiment ! Je me suis renseigné dans les articles scientifiques actuels, mais je n'ai rien trouvé qui correspond à votre description :/ Merci !!
EDIT : en tout cas, tu ne peux pas faire ça sans aller demander sa permission à Qemu, a minima. Donc soit c'est lui qui t'ouvre une trappe, soit tu modifies Qemu pour faciliter l'ouverture de cette trappe.
- Edité par Ksass`Peuk 8 septembre 2017 à 14:18:14
Merci Ksass, je connaissais déjà ce mécanisme ! On l'optimise en évitant leurs copies De leur côté, ils mettent en place un tampon de mémoire partagé entre les VM ou une VM et l'hyperviseur et lorsque des données arrivent, ils copient la donnée de la VM1 dans le tampon puis du tampon dans la VM2. Nous on alloue directement de l'espace mémoire dans notre tampon circulaire (avec une fonction similaire à malloc mais qui alloue de la mémoire dans le tampon) et la donnée est directement écrite et lue dans le tampon, elle n'existe pas ailleurs. Cela supprime les copies de données et boost le temps d'exécution des applications effectuant beaucoup de communication entre la VM et l'hyperviseur. Le petit soucis étant au niveau de l'écriture et d'un ensemble de données (un tableau par exemple) qui recouvrerait la fin et le début du tampon (comme il est circulaire, quand on atteint la fin du tampon, on continue l'écriture ou la lecture au début du tampon). Si le tampon est projeté qu'une fois en mémoire, il n'est pas possible d'allouer un espace continu pour contenir ces données. D'où la double projection du tampon ! Si le tampon est projeté deux fois de manière contiguë, lorsqu'on arrive à la fin du tampon, on y revient au début :
J'ai déjà implémenté le mécanisme sous Xen et les résultats étaient bien au rendez-vous. Je cherche à présent à faire la même chose dans KVM/Qemu, mais les outils à disposition sont plus complexes à utiliser. J'essayais de faire ça sans devoir réécrire le module de partage de mémoire, mais mes recherches sur le fonctionnement de mmap tendent à m'indiquer que rien n'est prévu pour effectuer une double projection de pages en mémoire utilisateur de manière sûre. C'est un peu dommage... Il va sûrement falloir que je réécrive le module pour effectuer cette double projection depuis l'espace noyau !
Bah ouais t'as pas le choix et c'est assez logique puisque mmap est lié à l'OS virtualisé et pas à Qemu. Après, ce que tu peux éventuellement tenter, c'est de produire un module du côté de Qemu (et en paravirtualisation du côté de tes VM) qui a te permettre de simplement rediriger mmap. Mais c'est valable que comme PoC. Après, il faut que ce soit dissocié de mmap sinon c'est une faille de sécurité.
C'a beaucoup dérivé, mais ma question initiale n'a effectivment rien à voir avec QEMU. Ma question c'est : j'ai un fichier, je souhaite monter ses pages deux fois, côte à côte, comment faire ? Après prise de renseignement, il semble Linux ne prévoit rien pour garantir ce besoin. Il est donc effectivement nécessaire de créer un module pour Linux pour ajouter cette fonctionnalité (qui me semble pourtant assez basique :/).
Problème de mapping
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Pas d'aide concernant le code par MP, le forum est là pour ça :)
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C