Allocation dynamique de la mémoire
Gestion de la mémoire dynamique par le noyau Linux
Il est courant que les modules noyaux doivent faire appel à des allocations dynamiques de la mémoire pour la création d’objets ou de structures de données.
Linux dispose d’une infrastructure très puissante pour couvrir ces besoins. Cette infrastructure est répartie sur trois niveaux.
- Les allocateurs
kmalloc
etvmalloc
offrant des services de base aux applications fonctionnant dans le noyau. De ces deux allocateurs, on préférera généralement utiliserkmalloc
pour ses performances. - Les allocateurs SLAB permettent de créer de caches, lesquels
contiennent des objets de même taille (voir
/proc/slabinfo
). Il existe différentes implémentations de ces allocateurs et peuvent être choisies lors de la configuration du noyau - Les allocateurs de pages permettent d’allouer de grandes zones mémoires, bien que dépendant de l’architecture, usuellement des blocs de 4KiB.
Allocateur kmalloc
kmalloc
est l’allocateur de mémoire d’usage général pour les modules du noyau Linux
- Il permet d’allouer des objets jusqu’à 128 MiB
- Pour les petites tailles, il s’appuie sur les caches génériques SLAB, nommés
kmalloc-XXX
ousize-xxx
(voir/proc/slabinfo
) - Pour de plus grandes tailles, il utilise sur l’allocateur de pages
kmalloc
garantit que la zone allouée est physiquement contigüe
Signification des drapeaux (flags)
GFP_KERNEL
: allocation mémoire standardGFP_ATOMIC
: permet d’allouer de la mémoire dans du code ne pouvant être interrompu (interrupt handler ou sections critiques)GFP_DMA
: permet d’allouer de la mémoire pouvant être utilisée pour des transferts DMA, on préférera cependant les services de l’interface<linux/dma-mapping.h>
, par exempledma_alloc_coherent()
- Plus de détails dans
<linux/gfp.h>
kmalloc
doit être utilisé comme l’allocateur principal à moins qu’il
existe une bonne raison d’utiliser un autre
Fonctions pour l’allocation de mémoire dans <linux/slab.h>
:
void* kmalloc (size_t size, gfp_t flags)
→ allouesize
octets et retourne le pointeur sur le bloc de données (adresse virtuelle)void* kzalloc (size_t size, gfp_t flags)
→ alloue et initialise à zéro le blocvoid* kcalloc (size_t n, size_t size, gfp_t flags)
→ alloue de la mémoire pourn
éléments de taillesize
et initialise à zéro le contenuvoid* krealloc (const void* p, size_t new_size, gfp_t flags)
→ change la taille du bloc pointé parp
pour la taillenew_size
. Le bloc est réalloué et son contenu copié.
Libération de mémoire :
void kfree (const void* objp)
-> libère la mémoire allouée
Exemple :
char* buffer = kzalloc (1000, GFP_KERNEL);
if (buffer == NULL) /* error handling... */;
// ... do some work
kfree (buffer);
buffer = 0;
Pour la réalisation de pilotes de périphériques, il existe également des services avec une libération automatique des blocs lorsque le module ou le périphérique est extrait.
void* devm_kmalloc (struct device* dev, size_t size, gfp_t flags);
void* devm_kzalloc (struct device* dev, size_t size, gfp_t flags);
void* devm_kcalloc (struct device* dev, size_t n, size_t size, gfp_t flags);
Pour une libération immédiate du bloc mémoire
void devm_kfree (struct device* dev, const void* objp);