Quelle est la haute memory et la faible memory sur Linux?

Je suis intéressé par la différence entre Highmem et Lowmem:

  1. Pourquoi y a-t-il une telle différenciation?
  2. Que gagnons-nous en le faisant?
  3. Quelles caractéristiques ont chacune?

Sur une architecture 32 bits, la plage d'espace d'adressage pour l'adressage de la memory vive est:

0x00000000 - 0xffffffff 

ou 4'294'967'295 (4 Go).

Le kernel Linux divise cette valeur par 3/1 (peut aussi être 2/2, ou 1/3 1 ) dans l'espace user (memory élevée) et l'espace kernel (memory faible).

La plage d'espace user:

 0x00000000 - 0xbfffffff 

Chaque process user nouvellement engendré reçoit une adresse (scope) dans cette zone. Les process users sont généralement non fiables et sont donc interdits d'access à l'espace kernel. En outre, ils sont considérés comme non urgents, en règle générale, le kernel essaie de reporter l'allocation de memory à ces process.

La plage d'espace kernel:

 0xc0000000 - 0xffffffff 

Un kernel traite son adresse (plage) ici. Le kernel peut accéder directement à ces 1 Go d'adresses (bien, pas le plein 1 Go, il y a 128 Mo réservés pour l'access à haute memory).

Les process générés dans l'espace kernel sont fiables, urgents et supposés sans erreur, la request de memory est traitée instantanément.

Chaque process du kernel peut également accéder à la plage d'espace user s'il le souhaite. Et pour y parvenir, le kernel mappe une adresse de l'espace user (la memory haute) vers son espace kernel (la memory faible), les 128 Mo mentionnés ci-dessus sont spécialement réservés pour cela.


1 Si la division est de 3/1, 2/2 ou 1/3, elle est contrôlée par l'option CONFIG_VMSPLIT_... ; vous pouvez probablement vérifier sous /boot/config* pour voir quelle option a été sélectionnée pour votre kernel.

La première reference à se tourner vers Linux Device Drivers (disponible 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 en mesure de mapper toute la memory dont il a besoin d'accéder. Et c'est le cas des process sur Linux et la plupart des systèmes d'exploitation: un process 32 bits ne peut accéder qu'à un peu less de 2 ^ 32 octets de memory virtuelle (en fait environ 3 Go sur une architecture Linux 32 bits typique). Cela devient difficile pour le kernel, qui doit pouvoir mapper la memory complète du process dont l'appel système est en cours d'exécution, plus toute la memory physique, ainsi que tout autre périphérique matériel mappé en memory.

Ainsi, lorsqu'un kernel 32 bits doit mapper plus de 4 Go de memory, il doit être compilé avec un support memory élevé. La memory haute est une memory qui n'est pas mappée en permanence dans l'espace d'adressage du kernel. (La memory faible est le contraire: elle est toujours mappée, vous pouvez donc y accéder simplement en déréférençant un pointeur.)

Lorsque vous accédez à la memory haute à partir du code du kernel, vous devez d'abord appeler kmap pour get un pointeur à partir d'une structure de données de page ( struct page ). Appeler kmap fonctionne si la page est dans la memory haute ou basse. Il y a aussi kmap_atomic qui a des contraintes supplémentaires mais qui est plus efficace sur les machines multiprocesseurs car il utilise un locking plus fin. Le pointeur obtenu via kmap est une ressource: il utilise l'espace adresse. Une fois que vous avez terminé, vous devez appeler kunmap (ou kunmap_atomic ) pour libérer cette ressource; le pointeur n'est plus valide et le contenu de la page est kmap tant que vous kmap encore appelé kmap .

Ceci est pertinent pour le kernel Linux; Je ne sais pas comment un kernel Unix gère cela.

La memory élevée est le segment de memory que les programmes d'espace user peuvent adresser. Il ne peut pas toucher la memory faible.

La memory faible est le segment de memory que le kernel Linux peut adresser directement. Si le kernel doit accéder à la memory élevée, il doit d'abord le mapper dans son propre espace d'adressage.

Il y a eu un patch récemment introduit qui vous permet de contrôler où se trouve le segment. Le compromis est que vous pouvez prendre la memory adressable loin de l'espace user afin que le kernel peut avoir plus de memory qu'il n'a pas à cartographier avant d'utiliser.

Ressources additionnelles:

HIGHMEM est une plage d'espace memory du kernel, mais ce n'est PAS de la memory, mais c'est un endroit où vous mettez ce que vous voulez accéder.

Une carte de memory virtuelle Linux typique de 32 bits est comme:

  • 0x00000000-0xbfffffff: process user (3 Go)

  • 0xc0000000-0xffffffff: espace kernel (1 Go)

(Vecteur spécifique au CPU et tout ce qui est ignoré ici).

Linux divise l'espace du kernel de 1 Go en deux parties, LOWMEM et HIGHMEM. La division varie d'une installation à l'autre.

Si une installation choisit, par exemple, 512 Mo-512 Mo pour les mems LOW et HIGH, le LOWMEM 512 Mo (0xc0000000-0xdfffffff) est mappé statiquement au moment du démarrage du kernel; généralement le premier nombre d'octets de la memory physique est utilisé pour que les adresses virtuelles et physiques de cette plage aient un décalage constant de, par exemple, 0xc0000000.

D'autre part, ce dernier 512 Mo (HIGHMEM) n'a pas de mappage statique (bien que vous puissiez laisser des pages partiellement mappées là-bas, mais vous devez le faire explicitement dans votre code de pilote). Au lieu de cela, les pages sont temporairement mappées et non mappées ici, de sorte que les adresses virtuelles et physiques de cette plage n'ont pas de correspondance cohérente. Les utilisations typiques de HIGHMEM incluent des tampons de données à time unique.

Pour autant que je me souvienne, "High Memory" est utilisé pour l'espace d'application et "Low Memory" pour le kernel.

Avantage est que les applications (espace user) ne peuvent pas accéder à la memory de l'espace kernel.

Beaucoup de gens ont dit que la memory faible est pour le operating system. Cela est généralement vrai, mais ne doit pas être. La memory élevée et la memory insuffisante ne sont que deux parties de l'espace memory, mais dans le système Linux, la faible memory est réservée au kernel et à la haute memory pour les process user.

Selon le "Livre des dinosaures (concepts du operating system)", nous pouvons placer le operating system dans une memory faible ou haute. Le principal facteur affectant cette décision est l'location du vector d'interruption. Comme le vector d'interruption est souvent en memory insuffisante, les programmeurs placent généralement le operating system en memory faible.