linux-kernel - Quelle est la différence entre vmalloc et kmalloc?





(7)


Quels sont les avantages d'avoir un bloc de mémoire contigu? Plus précisément, pourquoi aurais-je besoin d'avoir un bloc de mémoire physique contigu dans un appel système? Y a-t-il une raison pour laquelle je ne pourrais pas simplement utiliser vmalloc?

De "J'ai de la chance" de vmalloc sur vmalloc :

kmalloc est le moyen préféré, tant que vous n'avez pas besoin de très grandes surfaces. Le problème est que, si vous voulez faire du DMA de / vers un périphérique matériel, vous devrez utiliser kmalloc, et vous aurez probablement besoin d'un plus gros morceau. La solution consiste à allouer de la mémoire dès que possible, avant que la mémoire ne soit fragmentée.

J'ai fait un tour de kmalloc et j'ai trouvé la plupart des gens qui préconisaient l'utilisation de kmalloc , car vous avez la garantie d'avoir des blocs de mémoire physiques contigus. Cependant, il semble également que kmalloc peut échouer si un bloc physique contigu que vous voulez ne peut pas être trouvé.
Quels sont les avantages d'avoir un bloc de mémoire contigu? Plus précisément, pourquoi aurais-je besoin d'avoir un bloc de mémoire physique contigu dans un appel système ? Y a-t-il une raison pour laquelle je ne pourrais pas simplement utiliser vmalloc ?
Enfin, si je devais allouer de la mémoire lors du traitement d'un appel système, devrais-je spécifier GFP_ATOMIC ? Un appel système est-il exécuté dans un contexte atomique?

GFP_ATOMIC
L'allocation est prioritaire et ne dort pas. C'est le drapeau à utiliser dans les gestionnaires d'interruption, les moitiés inférieures et d'autres situations où vous ne pouvez pas dormir.

GFP_KERNEL Ceci est une allocation normale et pourrait bloquer. C'est l'indicateur à utiliser dans le code de contexte de processus quand il est sûr de dormir.




Les fonctions kmalloc() et vmalloc() sont une interface simple pour l'obtention de la mémoire du noyau dans les blocs de taille octet.

  1. La fonction kmalloc() garantit que les pages sont physiquement contiguës (et quasiment contiguës).

  2. La fonction vmalloc() fonctionne de manière similaire à kmalloc() , sauf qu'elle alloue de la mémoire qui est seulement contiguë et pas nécessairement contiguë physiquement.




Vous n'avez besoin de vous soucier de l'utilisation de la mémoire contiguë physiquement que si un périphérique DMA accède au tampon sur un bus physiquement adressé (comme PCI). Le problème est que de nombreux appels système n'ont aucun moyen de savoir si leur tampon sera éventuellement transmis à un périphérique DMA: une fois que vous passez le tampon à un autre sous-système du noyau, vous ne pouvez vraiment pas savoir où il va aller. Même si le noyau n'utilise pas le tampon pour DMA aujourd'hui, un développement futur pourrait le faire.

vmalloc est souvent plus lent que kmalloc, car il peut avoir à remapper l'espace tampon dans une plage pratiquement contiguë. kmalloc ne remappe jamais, mais s'il n'est pas appelé avec GFP_ATOMIC kmalloc peut bloquer.

kmalloc est limité dans la taille du tampon qu'il peut fournir: 128 Ko *) . Si vous avez besoin d'un très gros tampon, vous devez utiliser vmalloc ou un autre mécanisme comme la réservation de mémoire élevée au démarrage.

*) Cela était vrai pour les noyaux antérieurs. Sur les noyaux récents (j'ai testé cela sur 2.6.33.2), la taille maximale d'un seul kmalloc est de 4 Mo! (J'ai écrit un post assez détaillé à ce sujet .) - kaiwan

Pour un appel système, vous n'avez pas besoin de passer GFP_ATOMIC à kmalloc (), vous pouvez utiliser GFP_KERNEL. Vous n'êtes pas un gestionnaire d'interruption: le code de l'application entre dans le contexte du noyau au moyen d'un piège, ce n'est pas une interruption.




Linux Kernel Development de Robert Love (Chapitre 12, page 244 en 3ème édition) répond très clairement à cette question.

Oui, la mémoire physiquement contiguë n'est pas requise dans la plupart des cas. La raison principale pour que kmalloc soit utilisé plus que vmalloc dans le noyau est la performance. Le livre explique que, lorsque de gros morceaux de mémoire sont alloués à l'aide de vmalloc, le noyau doit mapper les morceaux physiques non-contigus (pages) dans une seule région de mémoire virtuelle contiguë. Comme la mémoire est virtuellement contiguë et physiquement non contiguë, plusieurs mappages d'adresses virtuelles à physiques devront être ajoutés à la table de pages. Et dans le pire des cas, il y aura le nombre de mappages (taille du tampon / taille de la page) ajouté à la table des pages.

Cela ajoute également une pression sur TLB (les entrées de cache stockant les mappages d'adresses virtuelles à physiques récents) lors de l'accès à ce tampon. Cela peut entraîner des thrashing .




Réponse courte: téléchargez Linux Device Drivers et lisez le chapitre sur la gestion de la mémoire.

Sérieusement, il y a beaucoup de problèmes subtils liés à la gestion de la mémoire du noyau que vous devez comprendre - je passe beaucoup de temps à déboguer les problèmes avec.

vmalloc () est très rarement utilisé, car le noyau utilise rarement de la mémoire virtuelle. kmalloc () est ce qui est généralement utilisé, mais vous devez savoir quelles sont les conséquences des différents drapeaux et vous avez besoin d'une stratégie pour gérer ce qui se passe en cas d'échec - en particulier si vous êtes dans un gestionnaire d'interruption, comme vous l'avez suggéré.




L'une des autres différences est que kmalloc renvoie une adresse logique (sinon vous spécifiez GPF_HIGHMEM). Les adresses logiques sont placées en "mémoire insuffisante" (dans le premier gigaoctet de mémoire physique) et sont mappées directement aux adresses physiques (utilisez la macro __pa pour la convertir). Cette propriété implique que la mémoire kmalloced est une mémoire continue.

D'autre part, Vmalloc est capable de renvoyer des adresses virtuelles à partir de "haute mémoire". Ces adresses ne peuvent pas être converties directement en adresses physiques (vous devez utiliser la fonction virt_to_page).




J'avais le même doute que toi jusqu'à ce que je tombe sur ce book du gourou C ++ Scott Meyers. Reportez-vous au troisième élément de ce livre où il parle en détail de l'utilisation de const .

Suivez simplement ce conseil

  1. Si le mot const apparaît à gauche de l'astérisque, ce qui est indiqué est constant
  2. Si le mot const apparaît à droite de l'astérisque, le pointeur lui-même est constant
  3. Si const apparaît des deux côtés, les deux sont constants




c linux-kernel kmalloc vmalloc