Sur une architecture 32 bits, la plage d'espace d'adressage pour l'adressage de la RAM est :
0x00000000 - 0xffffffff
ou 4'294'967'295
(4 Go).
Le noyau Linux divise cela en 3/1 (peut également être 2/2 ou 1/3 ) en espace utilisateur (mémoire élevée) et espace noyau (mémoire faible) respectivement.
La plage de l'espace utilisateur :
0x00000000 - 0xbfffffff
Chaque processus utilisateur nouvellement généré obtient une adresse (plage) à l'intérieur de cette zone. Les processus utilisateur ne sont généralement pas fiables et il leur est donc interdit d'accéder à l'espace du noyau. De plus, ils sont considérés comme non urgents, en règle générale, le noyau essaie de différer l'allocation de mémoire à ces processus.
La plage d'espace du noyau :
0xc0000000 - 0xffffffff
Un processus du noyau obtient son adresse (plage) ici. Le noyau peut accéder directement à ces 1 Go d'adresses (enfin, pas le 1 Go complet, il y a 128 Mo réservés pour un accès mémoire élevé).
Les processus générés dans l'espace noyau sont fiables, urgents et supposés sans erreur, la demande de mémoire est traitée instantanément.
Chaque processus du noyau peut également accéder à la plage d'espace utilisateur s'il le souhaite. Et pour y parvenir, le noyau mappe une adresse de l'espace utilisateur (la mémoire haute) vers son espace noyau (la mémoire basse), les 128 Mo mentionnés ci-dessus sont spécialement réservés à cela.
Que le partage soit 3/1, 2/2 ou 1/3 est contrôlé par le CONFIG_VMSPLIT_...
option; vous pouvez probablement vérifier sous /boot/config*
pour voir quelle option a été sélectionnée pour votre noyau.
La première référence vers laquelle se tourner est Linux Device Drivers (disponible à la fois en ligne et sous forme de livre), en particulier le chapitre 15 qui contient une section sur le sujet.
Dans un monde idéal, chaque composant du système serait capable de mapper toute la mémoire à laquelle il a besoin d'accéder. Et c'est le cas pour les processus sous Linux et la plupart des systèmes d'exploitation :un processus 32 bits ne peut accéder qu'à un peu moins de 2^32 octets de mémoire virtuelle (en fait environ 3 Go sur une architecture Linux 32 bits typique). Cela devient difficile pour le noyau, qui doit être capable de mapper la mémoire complète du processus dont l'appel système est en cours d'exécution, plus toute la mémoire physique, plus tout autre périphérique matériel mappé en mémoire.
Ainsi, lorsqu'un noyau 32 bits doit mapper plus de 4 Go de mémoire, il doit être compilé avec une prise en charge élevée de la mémoire. La mémoire haute est une mémoire qui n'est pas mappée en permanence dans l'espace d'adressage du noyau. (La mémoire faible est le contraire :elle est toujours mappée, vous pouvez donc y accéder dans le noyau simplement en déréférencant un pointeur.)
Lorsque vous accédez à la mémoire haute à partir du code du noyau, vous devez appeler kmap
d'abord, pour obtenir un pointeur à partir d'une structure de données de page (struct page
). Appel kmap
fonctionne que la page soit en mémoire haute ou basse. Il y a aussi kmap_atomic
qui a ajouté des contraintes mais est plus efficace sur les machines multiprocesseurs car il utilise un verrouillage plus fin. Le pointeur obtenu via kmap
est une ressource :elle utilise de l'espace d'adressage. Une fois que vous avez terminé, vous devez appeler le kunmap
(ou kunmap_atomic
) pour libérer cette ressource ; alors le pointeur n'est plus valide et le contenu de la page n'est plus accessible tant que vous n'appelez pas kmap
à nouveau.
Ceci est pertinent pour le noyau Linux; Je ne sais pas comment un noyau Unix gère cela.
La mémoire haute est le segment de mémoire que les programmes de l'espace utilisateur peuvent adresser. Il ne peut pas toucher la mémoire faible.
La mémoire faible est le segment de mémoire que le noyau Linux peut adresser directement. Si le noyau doit accéder à la mémoire haute, il doit d'abord la mapper dans son propre espace d'adressage.
Il y a eu un patch introduit récemment qui vous permet de contrôler où se trouve le segment. Le compromis est que vous pouvez retirer de la mémoire adressable de l'espace utilisateur afin que le noyau puisse avoir plus de mémoire qu'il n'a pas à mapper avant de l'utiliser.
Ressources supplémentaires :
- http://tldp.org/HOWTO/KernelAnalysis-HOWTO-7.html
- http://linux-mm.org/HighMemory