9
votes

Comment redimensionner les régions allouées par Virtualalloc?

Je voudrais redimensionner une région de mémoire allouée par Virtualalloc de Mme Window. En regardant la documentation Virtualfree, il est possible de déclencher une région en partie, mais il n'est pas possible de le relâcher partiellement. C'est-à-dire qu'il est possible de libérer une partie de la mémoire physique, mais ne faisant pas partie de la mémoire virtuelle.

Je suis conscient qu'il peut être nécessaire de réaffecter la région dans un tel cas. Cependant, la copie sur toute la région serait plutôt inefficace. Y a-t-il un moyen de demander à Windows d'allouer une nouvelle région avec une taille différente, qui pointe vers la même mémoire?


5 commentaires

Tout le point de la mémoire virtuelle est de résumer ces affaires et de laisser le noyau traiter avec le placement de la mémoire.


Votre application doit-elle libérer des pages de mémoire virtuelle? Êtes-vous à court d'espace d'adressage virtuel?


@Danieltrebbien: La situation est la suivante. J'ai besoin d'une nouvelle région, alors j'essaie de l'allouer avec Virtualalloc. Cependant, Virtualalloc jette une mémoire de mémoire. Dans le même temps, à cause de certaines métadonnées, je me tiens moi-même, je sais que certaines régions ne sont que à moitié plein. J'aimerais maintenant rétrécir ou realloc ces régions à moindre coût jusqu'à ce que je reçois de nouveau la mémoire.


Vous ne pouvez pas faire ce travail. Les allocations en mouvement ne sont possibles qu'avec un collecteur de déchets pouvant suivre les pointeurs et les mettre à jour. DÉCOMMISSANCE Les régions ne rétrécissent pas la répartition, mais simplement les déménager. Vous découvrez pourquoi Malloc () fonctionne comme ça.


Il n'y a pas de pointeurs non cochés qui référencent les pages. C'est bien si les adresses VMEM sont modifiées. C'est-à-dire que quelque chose comme Realloc serait assez bon, tant que c'est rapide.


3 Réponses :


1
votes

Pas une réponse, mais je dois demander:

Compte tenu de la douleur dans laquelle vous vous trouvez, les succès de la performance de Virtualalloc () et la non-portabilité de votre code; Comme contre toute valeur Virtualalloc () donne, pourriez-vous peut-être envisager d'utiliser Malloc () et des amis? Iow, Virtualalloc () confère un avantage réel?

À mon avis (peut-être seulement mon avis), le pouvoir et la généralité de MALLOC () l'emportent sur l'ensemble de l'attrait que Virtualalloc () promet. Et cela vous permettrait de traiter vos régions beaucoup plus simples.

Désolé pour la réponse non-réponse. Je déteste-le quand les gens demandent "qui jamais serait même penser faire que ?" Mais bien sûr, tout est différent quand je suis celui qui demande "pourquoi" :-)


4 commentaires

Simple, j'écris mon propre gestionnaire de mémoire de niveau Malloc parce que Malloc n'est pas efficace pour ce que je fais


@CIB, dans la plupart des cas, même si l'utilisation directe de MALLOC est inefficace, une utilisation indirecte de MALLOC (c.-à-d. MALLOC pour obtenir un bloc important que vous avez encore subditivé) est généralement correct ...


@bdonlan: C'est peut-être le cas, mais cela ressemble à un hack au mieux. En utilisant MALLOC, vous avez peu de contrôle sur l'endroit où vous allouez. Par exemple, certaines de mes exigences incluent probablement une alignement de page et des adresses dans une certaine gamme d'adresses. Bien sûr, certaines implémentations MALLOC peuvent déterminer, mais comme Malloc est abstrait, vous ne pouvez jamais être sûr.


@CIB - Il est assez facile de rendre l'adresse renvoyée par Malloc () être alignée sur une page ou autre chose. Après tout, Virtualalloc () le fait; pourquoi pas toi? Je me penche sur cela parce que, pour dire la vérité, vous clouez-vous, fermez le cercueil de la portabilité lorsque vous appelez une fonction exclusive. Vous pourriez dire: "Eh bien, ça va" être utilisé sous windows , fer chrissake! " Oui, j'ai dit que plusieurs fois, seulement pour me frapper plus tard.



1
votes

Si vous souhaitez réduire une allocation, vous pouvez utiliser virtualfree avec mem_decommit sur une sous-bande de l'allocation. Notez que cela ne libérera pas espace d'adresse ; seulement une bélière physique. Si vous voulez le développer, vous pouvez essayer virtualalloc transmettre une adresse immédiatement après votre allocation existante. Cela peut bien sûr échouer, à quel point vous devez copier la mémoire.

Vous pouvez également essayer d'utiliser globallalloc avec gmem_movileable et globalresalloc (ou les fonctions de tas équivalents *).

Si vous avez besoin d'un espace d'adressage gratuit, vous pouvez essayer d'utiliser des objets de mappage de mémoire anonyme et de modifier leur fenêtre mappée au moment de l'exécution - ou utilisez simplement 64 bits pour obtenir un espace d'adresses supplémentaire.


2 commentaires

N'aide pas, il est hors de l'espace d'adressage. Virtualalloc / Free n'a rien à voir avec la RAM sur un système d'exploitation de mémoire virtuelle à la demande de la demande.


@Hanspassant, voir ma dernière suggestion - Il peut utiliser des objets de mappage de mémoire anonyme et carapez les fenêtres d'entre elles. Ou juste aller à 64 bits.



5
votes

Comme vous l'avez mentionné, il ne semble pas être possible de libérer partiellement une gamme de pages réservées car le virtualfree () Documentation états:

Si le paramètre dwfreetype est Mem_Release, [ lpaddress ] doit être l'adresse de base renvoyée par le VERTUALALLALLOC Fonction lorsque la région des pages [était] réservée.

ainsi que:

Si le paramètre dwfreetype est Mem_Release, [ dwsize ] doit être 0 (zéro).

virtualfree () est lui-même une mince emballage de la fonction de noyau NTFreeVirtualMemory () . sa page de documentation (la même chose que pour zwfreevirtualmemory () < / Code>) a aussi ce libellé.

Un travail possible est de diviser une seule réservation importante avec plusieurs plus petites. Par exemple, supposons que vous réserve normalement 8 mib d'espace d'adresses virtuel à la fois. Vous pourriez plutôt tenter de réserver la gamme dans trente-deux réservations contiguës 256 KIB. La première réservation de 256 kib contiendrait un champ de bits non signé 32 bits, où le bit i TH est défini si le i th 256 kib réservation a été obtenue: xxx

sortie d'échantillon: xxx

EDIT: J'ai constaté qu'il est beaucoup mieux de "pré-réserver" les trente-deux 256 plages de 256 kib à la fois, libres, puis tentent de ré-réserver autant que vous le pouvez.

i Mise à jour du code et de l'échantillon de sortie ci-dessus.

Dans un environnement multithreadé, le code peut revenir à la liste "Place n'importe où" de la première réservation. Peut-être est-il une bonne idée de tenter de réserver réservation_size octets à une gamme réservée à libération de 32 * réservation_size_size d'octets de cinq fois, tombant enfin à la "place n'importe où "allocation.


5 commentaires

Intéressant, j'ai eu la même idée, mais je n'étais pas sûr si cela serait efficace ou comment cela serait fait en détail. En fait, si j'y pense, un bitmap n'est même pas nécessaire, puisque je ne me rétrécirai que la "région". Ainsi, un compteur de pages actuellement allouées devrait suffire. Quoi qu'il en soit, merci beaucoup pour le code, dommage que je ne puisse pas voter plus d'une fois.


@CIB: Je ne suis pas sûr que vous puissiez obtenir sans le bitmap. Cela peut arriver, par exemple, que la 32e réservation ne pouvait pas être obtenue. Même si vous protectez tous les appels vers VirtualALLOC () avec un mutex, il est possible pour un autre processus d'attribution de l'espace d'adresses virtuel dans l'espace d'adressage de votre processus via VirtualallOcex () .


Je pense qu'une fois que je suis incapable de fournir une pièce de mémoire contiguë, je dois réaffecter ou élever une erreur. Si ma "région" a des trous, je ne peux pas l'utiliser comme un seul morceau de mémoire, mais je dois plutôt le traiter comme ce qu'il est, une collection de pages séparées. De plus, alors que cela est un peu hors sujet, pouvez-vous expliquer pourquoi les autres processus peuvent vouloir allouer de la mémoire dans mon processus? Cela ressemble à quelque chose qui ne sera pas sûr de toute façon, sans un système d'autorisation inter-processus approprié.


@CIB: Je n'ai utilisé que virtualallocex () une fois pour allouer une mémoire dans explorateur.exe . IIRC, j'avais besoin d'allouer de l'espace pour une structure spécifique dans l'espace d'adresses de l'Explorer afin d'envoyer un message à l'une des fenêtres de l'explorateur (correspondant à la "zone de notification" de la barre de démarrage). Cette fenêtre remplirait la structure avec des informations. J'ai ensuite appelé readprocessmemorory () pour lire ce qu'il a écrit, suivi de virtualfree () afin que je ne fasse pas la mémoire de l'explorateur. Voici quelque chose de similaire: Autohotkey.com/forum/topic5825.html


Ah. Eh bien, je n'ai pas l'intention de faire appel à de telles caractéristiques, donc s'il y a un programme qui tente quelque chose comme ça et brise les choses, c'est acceptable pour moi. Je pense que le problème plus grand ici est des threads dans mon propre processus qui utilisent régulièrement Malloc.