2010-12-01 5 views
8

Je souhaite conserver l'espace d'adressage virtuel réservé dans mon processus pour la mémoire qui était précédemment utilisée mais qui n'est pas actuellement nécessaire. Je m'intéresse à la situation où le noyau de l'hôte est Linux et il est configuré pour empêcher les surcharges (ce qu'il fait par la comptabilité détaillée de toute la mémoire engagée).Est-ce que mmap/mprotect-readonly zero pages compte pour la mémoire validée?

Si je veux juste éviter les données que ma demande n'utilise plus d'occuper la mémoire physique ou se permuté sur le disque (gaspillage de ressources soit façon), je peux madvise le noyau qu'il est inutile, ou mmap nouvelles zéro pages sur en haut. Mais aucune de ces approches ne réduira nécessairement la quantité de mémoire qui compte comme commise, que d'autres processus sont alors empêchés d'utiliser. Que se passe-t-il si je remplace les pages par de nouvelles pages zéro marquées en lecture seule? Mon intention est qu'ils ne comptent pas dans la mémoire validée, et que je puisse ensuite utiliser mprotect pour les rendre accessibles en écriture, et que cela échouerait si leur écriture dépassait la limite de mémoire validée. Est-ce que ma compréhension est correcte? Est-ce que ça va marcher?

+1

Une page en lecture seule ne doit pas être considérée dans un processus de validation (je n'ai pas de référence à portée de main, donc ce n'est pas une réponse), et Linux fournit le drapeau MAP_NORESERVE qui devrait vous donner un garantie. Mais je dois demander: pourquoi ressentez-vous le besoin de réserver de la mémoire qui n'est pas utilisée? – Anon

+0

Les mauvaises choses (tm) se produiraient si les mêmes adresses virtuelles étaient allouées par 'mmap' (au hasard) sans que le programme en soit conscient. :-) En ce qui concerne 'MAP_NORESERVE', je m'inquiète que cela empêche les pages d'être comptées même après que je les ai protégées par écrit plus tard. Je suppose que je pourrais juste «mmap» sur eux encore avec de nouvelles pages zéro. –

+0

Quelles mauvaises choses arriveraient? Pourquoi votre programme n'a-t-il jamais besoin de réutiliser l'espace d'adressage utilisé précédemment? Cela semble très inhabituel. – Angus

Répondre

1

Si vous n'utilisez pas la page (en lecture ou en écriture), elle ne sera pas validée dans votre espace d'adressage (réservé uniquement). Mais votre espace d'adressage est limité, vous ne pouvez donc pas jouer comme vous le souhaitez. Voir par exemple ElectricFence qui peut échouer pour un grand nombre d'allocations, en raison de l'insertion de "page page/guard nul" (mémoire anonyme sans accès). Jetez un oeil à ce fil: « mprotect() a échoué: Impossible d'allouer la mémoire »: http://thread.gmane.org/gmane.comp.lib.glibc.user/538/focus=976052

+3

Il * sera * facturé en taille virtuelle, mais pas en RSS. –

1

Sur Linux, en supposant overcommit n'a pas été désactivé, vous pouvez utiliser le drapeau MAP_NORESERVE à mmap, qui veillera à ce que la page en question ne sera pas comptabilisé comme mémoire allouée avant d'être accédé. Si la surcommande a été complètement désactivée, voir ci-dessous à propos des pages à mappage multiple. Notez que le comportement de Linux pour les pages zéro a parfois changé par le passé; avec certaines versions du noyau, il suffit de lire la page pour l'attribuer. Avec les autres, une écriture est nécessaire. Notez que les indicateurs de protection ne provoquent pas d'allocation directement; Cependant, ils peuvent vous empêcher de déclencher accidentellement une allocation. Par conséquent, pour des résultats plus fiables, vous devez éviter d'accéder à la page par mprotect avec PROT_NONE.

Comme une autre option, plus portable, vous pouvez mapper la même page à plusieurs emplacements. C'est-à-dire, créer et ouvrir un fichier temporaire vide, le dissocier, ftruncate à un nombre raisonnable de pages, puis mmap à plusieurs reprises à l'offset 0 dans le fichier. Cela garantira absolument la mémoire ne compte qu'une fois contre l'utilisation de la mémoire de votre programme. Vous pouvez même utiliser MAP_PRIVATE pour le réaffecter automatiquement lorsque vous écrivez sur la page. Cela peut avoir une utilisation de la mémoire plus élevée que la technique MAP_NORESERVE (à la fois pour les données de suivi du noyau, et pour les pages du fichier temporaire lui-même), donc je recommanderais d'utiliser MAP_NORESERVE à la place si disponible. Si vous utilisez cette technique, essayez de rendre la région mappée raisonnablement grande (et placez-la dans /dev/shm si sous Linux, pour éviter les E/S de disque). Chaque appel mmap consommera une certaine quantité de mémoire de noyau (non permutable) pour le suivre, il est donc bon de réduire ce compte.

+1

Informations utiles globalement, mais «MAP_NORESERVE» n'est pas utile. Il est ignoré lorsque la sur-validation est entièrement désactivée. –

+0

Pensez-vous que le mapping '/ dev/zero' fonctionnerait aussi bien qu'un fichier temporaire dans votre proposition? –

+0

@Zan, no. Les cartes '/ dev/zero' sont les mêmes que les cartes' MAP_ANON' ordinaires et seront donc comptabilisées comme n'importe quelle autre allocation de mémoire. – bdonlan

Questions connexes