Quelle est la différence entre vmalloc et kmalloc?

113

J'ai cherché sur Google et j'ai trouvé que la plupart des gens préconisaient l'utilisation de kmalloc, car vous êtes assuré d'obtenir des blocs physiques contigus de mémoire. Cependant, il semble également que cela kmallocpuisse échouer si un bloc physique contigu que vous souhaitez 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 peux pas simplement utiliser vmalloc?
Enfin, si je devais allouer de la mémoire lors du traitement d'un appel système, dois-je préciser GFP_ATOMIC? Un appel système est-il exécuté dans un contexte atomique?

GFP_ATOMIC
L'allocation est hautement prioritaire et ne se met pas en veille. 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 Il s'agit d'une allocation normale et pourrait bloquer. Il s'agit de l'indicateur à utiliser dans le code de contexte de processus lorsqu'il est prêt à dormir.

Mémoire libre
la source
4
Cet article revendique des absurdités telles que: "En général, une architecture 32 bits a une taille de page de 4 Ko et une architecture 64 bits a une taille de page de 8 Ko". Je ne l'ai pas entièrement lu, mais je ne l'appellerais pas «bon», ni même en ferais confiance.
Alexandro Sánchez
1
Remarque (semi-liée): vmallocest plus rapide avec Kernel 5.2 (Q2 2019)
VonC

Réponses:

96

Vous ne devez vous soucier de l'utilisation de la mémoire physiquement contiguë que si le tampon sera accédé par un périphérique DMA sur un bus adressé physiquement (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 réserver une mémoire élevée au démarrage.

*) C'était le cas des noyaux antérieurs. Sur les noyaux récents (j'ai testé ceci sur 2.6.33.2), la taille maximale d'un seul kmalloc est jusqu'à 4 Mo! (J'ai écrit un article assez détaillé à ce sujet .) - kaiwan

Pour un appel système, vous n'avez pas besoin de transmettre 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 trap, ce n'est pas une interruption.

DGentry
la source
1
Je pensais que les appels système étaient entrés en déclenchant int $ 0x80? (c'est-à-dire une interruption)?
FreeMemory le
2
int $ 0x80 est une interruption logicielle, également appelée trap. Ce que l'on entend par gestionnaires d'interruption est une interruption matérielle, par exemple lorsque l'utilisateur appuie sur une touche ou déplace les mouvements.
Branan le
Les appels système concernent les transitions entre l'espace utilisateur et l'espace noyau ... kmalloc est utilisé uniquement dans le contexte du noyau ??
AIB
3
@FreeMemory: int $ 0x80 est spécifique à x86, et puis, c'est aussi une ancienne méthode remplacée par sysenter / syscall (sur x86).
jørgensen
18

Réponse courte: téléchargez les pilotes de périphériques Linux 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 des problèmes avec.

vmalloc () est très rarement utilisé, car le noyau utilise rarement 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 indicateurs 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é.

Mike Heinz
la source
1
"parce que le noyau utilise rarement la mémoire virtuelle", pourquoi est-ce?
Trey
Parce que vous ne voulez généralement pas que le noyau bloque pendant qu'il attend que le noyau permute de la mémoire dans ou hors du stockage sur disque ...
Mike Heinz
Non, la mémoire du noyau allouée avec vmalloc n'est jamais permutée. Seule la mémoire de l'espace utilisateur peut être permutée. L'espace d'adressage du noyau n'est pas échangeable et vmalloc alloue dans l'espace d'adressage du noyau.
user2679859 le
13

Linux Kernel Development par Robert Love (Chapitre 12, page 244 de la 3e édition) répond très clairement à cela.

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

Cela ajoute également une pression sur TLB (les entrées de cache stockant les mappages d'adresses virtuelle à physique récents) lors de l'accès à ce tampon. Cela peut conduire à des raclées .

codetwiddler
la source
11

Les fonctions kmalloc()& vmalloc()sont une interface simple pour obtenir la mémoire du noyau par blocs de la taille d'un octet.

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

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

Yogeesh HT
la source
4

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 peux pas simplement utiliser vmalloc?

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

kmalloc est le moyen préféré, tant que vous n'avez pas besoin de très grandes zones. Le problème est que si vous voulez faire du DMA depuis / 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.

Shikari sombre
la source
Voyez, j'ai lu cela, et cela n'a pas de sens pour moi. Je comprends l'utilisation de kmalloc pour de grandes zones; mais pour les petites allocations, pourquoi ne pas utiliser vmalloc pour éviter de fragmenter la mémoire physique?
FreeMemory le
Parce que vous devez faire confiance au noyau pour faire ce qu'il y a de mieux; s'il pense qu'il est préférable d'allouer un seul morceau, il le fera. vmalloc n'est utilisé que lorsque vous devez absolument avoir un bloc contigu.
Dark Shikari le
Je suppose que cela a du sens, mais cela semble contre-intuitif. kmalloc semble devoir être utilisé lorsque les performances sont les plus importantes (c'est-à-dire que je ne peux pas être tourmenté par les E / S de disque). Et qu'en est-il de GFP_ATOMIC?
FreeMemory le
2

Sur un système 32 bits, kmalloc () renvoie l'adresse logique du noyau (c'est une adresse virtuelle cependant) qui a le mappage direct (en fait avec un décalage constant) à l'adresse physique. Ce mappage direct garantit que nous obtenons un morceau physique contigu de RAM. Convient pour DMA où nous ne donnons que le pointeur initial et attendons un mappage physique contigu par la suite pour notre opération.

vmalloc () renvoie l'adresse virtuelle du noyau qui à son tour peut ne pas avoir de mappage contigu sur la RAM physique. Utile pour une allocation de mémoire importante et dans les cas où nous ne nous soucions pas du fait que la mémoire allouée à notre processus est continue également dans la RAM physique.

a.saurabh
la source
1

Une des autres différences est que kmalloc retournera une adresse logique (sinon vous spécifiez GPF_HIGHMEM). Les adresses logiques sont placées en "mémoire faible" (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 allouée est une mémoire continue.

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

Jérôme Pouiller
la source