Pouvez-vous forcer un plantage si une écriture se produit à un emplacement de mémoire donnée avec plus fine que la granularité de la page?

StackOverflow https://stackoverflow.com/questions/2484959

Question

Je suis en train d'écrire un programme qui, pour des raisons de performance utilise la mémoire partagée (prises et conduites comme des alternatives ont été évaluées, et ils ne sont pas assez rapide pour ma tâche, de manière générale toute méthode IPC qui implique des copies est trop lent). Dans la région de mémoire partagée, je vous écris beaucoup struct d'une taille fixe. Il y a un programme responsable de la rédaction des struct en mémoire partagée, et de nombreux clients qui lisent de lui. Cependant, il est un membre de chaque struct que les clients ont besoin d'écrire (un compte de référence, qu'ils mettront à jour atomiquement). Tous les autres membres doivent être lus que les clients.

Parce que les clients ont besoin de changer qu'un membre, ils ne peuvent pas la carte de la région de mémoire partagée en lecture seule. Mais ils ne devraient pas être bricoler avec les autres membres non plus, et étant donné que ces programmes sont écrits en C ++, la corruption de mémoire est possible. Idéalement, il devrait être aussi difficile que possible pour un client à un autre plantage. Je suis seulement inquiet pour les clients buggy, pas méchants, si des solutions imparfaites sont autorisés.

Je peux essayer d'arrêter les clients en déclarant d'écraser les membres dans l'en-tête qu'ils utilisent comme const, mais cela n'empêchera pas la corruption de mémoire (dépassements de mémoire tampon, mauvais moulages, etc.) d'écraser. Je peux insérer canaries, mais je dois payer en permanence le coût de les vérifier.

Au lieu de stocker de l'élément de comptage de référence directement, je pouvais stocker un pointeur sur les données réelles dans une écriture cartographié séparée seulement la page, tout en gardant les struct en lecture des pages mappées seulement. Cela fonctionne, le système d'exploitation forcera mon application à se bloquer si je tente d'écrire sur le pointe aux données, mais le stockage indirect peut être indésirable en essayant d'écrire ce plutôt oeil popping papier, mais malheureusement, il nécessite l'utilisation de la mémoire ECC et un noyau Linux modifié.

Était-ce utile?

La solution

Je ne pense pas il est possible de faire quelques bits lus seulement comme ça au niveau du système d'exploitation.

Une chose qui me vient est maintenant produite que vous pourriez mettre les comptes de référence dans une autre page comme vous le suggérez. Si les struct sont d'une taille commune, et sont tous dans des emplacements de mémoire séquentielle vous pouvez utiliser l'arithmétique de pointeur pour localiser un compte de référence du pointeur de structures, plutôt que d'avoir un pointeur dans la structure. Cela pourrait être mieux que d'avoir un pointeur pour votre cas d'utilisation.

long *refCountersBase;//The start address of the ref counters page
MyStruct *structsBase;//The start address of your structures page

//get address to reference counter
long *getRefCounter(MyStruct *myStruct )
{
    size_t n = myStruct - structsBase;
    long *ref = refCountersBase + n;
    return ref;
}

Autres conseils

Vous devez ajouter un gestionnaire de signal pour SIGSEGV qui récupère de l'exception, mais seulement pour certaines adresses. Un point de départ pourrait être http://www.opengroup.org/onlinepubs /009695399/basedefs/signal.h.html et la documentation correspondante pour votre système d'exploitation.

Modifier Je crois que ce que vous voulez est d'effectuer l'écriture et retourner si l'adresse d'écriture est en fait OK, et la queue-appeler le gestionnaire d'exception précédente (le pointeur que vous obtenez lorsque vous installez votre exception gestionnaire) si vous voulez propager l'exception. Je ne suis pas vécu dans ces choses cependant.

Je ne l'ai jamais entendu parler de l'application en lecture seule à moins d'une granularité de page, de sorte que vous pourriez être hors de la chance dans cette direction, sauf si vous pouvez mettre chaque struct sur deux pages. Si vous pouvez vous permettre deux pages par struct vous pouvez mettre le compte de référence sur l'une des pages et de faire autre lecture seule.

Vous pouvez écrire une API plutôt que de simplement utiliser les en-têtes. Les clients forçant à utiliser l'API élimineront la plupart des problèmes de corruption.

Garder les données avec le nombre de référence plutôt que sur une autre page vous aidera avec localisation des données et ainsi améliorer les performances du cache.

Vous devez considérer qu'un lecteur peut avoir un problème et ne parviennent pas à mettre à jour correctement son compte réf. Que l'auteur peut ne pas terminer une mise à jour. Faire face à ces choses nécessite des contrôles supplémentaires. Vous pouvez combiner ces contrôles avec l'API. Il peut être intéressant d'expérimenter pour mesurer les conséquences sur les performances d'une sorte de vérification de l'intégrité. Il peut être assez rapide pour garder une somme de contrôle, quelque chose d'aussi simple que adler32.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top