J'ai appris ces sujets et lu de nombreux articles et livres, mais ils manquent tous d'informations complémentaires et m'ont encore plus troublé. Alors ici, je voudrais expliquer ce que je sais pendant que je pose mes questions. J'espère que ce sujet sera utile pour beaucoup comme moi. Je voudrais également apprendre la validité de mes connaissances et corriger si nécessaire.
Mémoire virtuelle
Certains articles disent que "la mémoire virtuelle est un espace du disque dur qui émule la mémoire physique afin que nous puissions avoir plus de mémoire que nous n'en avons réellement". Certains autres articles disent que "la mémoire virtuelle est la combinaison de la mémoire physique (RAM), une section du disque dur qui agit comme la mémoire physique et les tables de pages". Mais ce sont des choses différentes et je ne comprends pas pourquoi il y a différentes explications comme ça.
Passons à la deuxième explication, car c'est aussi la façon dont Wikipedia décrit également la mémoire virtuelle. À ce stade, l'adresse virtuelle est logique, car nous utilisons directement l'adresse de la mémoire virtuelle au lieu de la mémoire physique.
Soit dit en passant, mon Mac dit que j'ai 8 Go de mémoire physique et 8 Go de mémoire virtuelle. Dans ce cas, VM inclut la mémoire physique ou est-ce la quantité d'espace en HD utilisée comme mémoire? Ai-je 16 Go de mémoire disponible pour mes programmes?
Question 1:
Intel i5 possède un bus d'adresse 36 bits, ce qui signifie que vous pouvez adresser une mémoire de 64 Go. Disons que j'ai installé 4 Go RAM sur mon ordinateur. Cependant, mes programmes peuvent ne pas connaître la taille de la mémoire installée car elle sera utilisée sur de nombreux systèmes différents avec des tailles de mémoire différentes. est l'endroit où la mémoire virtuelle devient pratique. Elle résume la taille réelle de la mémoire installée.
Cependant, que se passe-t-il lorsque mes programmes souhaitent accéder à l'adresse mémoire 0xFFFFFFFFF? Je n'ai installé que 4 Go et peut-être un peu d'espace mémoire en HD.
J'ai deux théorie pour cette question:
1. Étant donné que les tables de pages sont gérées par le système d'exploitation, le système d'exploitation décode cette adresse et découvre quelle page est et vérifie cette page dans la table de pages pour voir si une adresse physique lui est associée (valide et drapeaux invalides), si oui, va à l'adresse physique aux points d'entrée de la page dans la mémoire physique + décalage défini dans l'adresse virtuelle et apporte cette valeur. Sinon, une erreur de page se produit et le système d'exploitation recherche cette page dans le stockage secondaire, la récupère et la met en mémoire et met à jour le tableau des pages.
2. Il lève une exception de type OutOfMemory qui dit que je n'ai pas de mémoire à laquelle l'adresse donnée peut adresser.
L'inconvénient de la première théorie est que ce qui se passe quand un programme veut utiliser 64 Go de mémoire? Ensuite, nous devons avoir 60 Go d'espace mémoire en HD car nous n'avons que 4 Go. Cependant, dans la capture d'écran ci-dessous, MAC me dit qu'il n'y a que 8 Go de mémoire virtuelle.
Question 2:
Comment les processus sont-ils placés dans la mémoire virtuelle? Je veux dire que chaque processus a-t-il de l'espace de mémoire virtuelle 0x0 - 0xFFFFFFFFF disponible pour eux ou qu'il n'y a qu'un seul espace d'adresse de mémoire virtuelle où tout le processus est placé?
Si chaque processus suppose qu'ils ont toute la mémoire disponible pour eux, les mémoires ressemblent à ceci:
S'il n'y a qu'un seul concept de mémoire virtuelle, cela ressemblerait à ceci:
Tableau de page
Le tableau des pages est donc une structure de données qui se situe entre les adresses physiques et les adresses virtuelles. C'est un tableau associatif (ou comme un dictionnaire) qui pour chaque page (clé), il y a une adresse physique associée (valeur).
Le système d'exploitation utilise MMU (unité de gestion de la mémoire) pour effectuer cette traduction d'une adresse virtuelle en une adresse physique.
Question 3:
Existe-t-il un grand tableau de pages géant qui inclut toutes les pages de chaque processus ou chaque processus a son propre tableau de pages?
Paging
La pagination est une méthode de gestion de la mémoire. La mémoire virtuelle et la mémoire physique sont divisées en pages (qui sont des blocs fixes et de même taille) par l'unité de gestion de la mémoire. Cette technique est utile lorsque vous échangez des pages entre la mémoire et le stockage secondaire afin de pouvoir échanger des pages entre elles. Votre programme demande par exemple des données situées dans une adresse. Cependant, cette adresse que votre programme utilise est une adresse virtuelle et MMU la traduit à l'aide du tableau des pages. Pendant cela, MMU vérifie le tableau des pages si la demande est présente) dans la table des pages et le système d'exploitation l'obtient du stockage secondaire sinon et met à jour la table des pages.
Question 4:
Supposons qu'un processus demande les données à une adresse qui est convertie en une adresse physique qui contient déjà certaines données. Comment sait-on que les données n'appartiennent pas aux processus demandeurs et doivent être remplacées par celles qui se trouvent dans le stockage secondaire?
Il y a un bit sale par exemple qui est utilisé pour réécrire cette page sur le disque dur ou non, mais je ne pense pas que ce soit ce qui détermine le processus propriétaire.
Certaines personnes utilisent le terme "mémoire virtuelle" comme s'il était synonyme du fichier de page, car le fichier de page représente la partie de votre mémoire allouée qui n'est pas de la mémoire "réelle" (c.-à-d. RAM). Mais la plupart des gens considèrent que la "mémoire virtuelle" est la couche d'abstraction entière que le système d'exploitation donne aux programmes, qui combine le RAM et le fichier d'échange.
Je ne sais pas laquelle de ces définitions est préférée par Mac OS, bien qu'il semble peu probable que votre ordinateur n'ait pas tout mémoire paginée allouée, donc je suppose qu'il ajoute probablement 8 Go de pagination mémoire à vos 8 Go de RAM réelle, pour un total de 16 Go de mémoire (virtuelle) disponible.
N'oubliez pas que, car le système d'exploitation gère les demandes d'allocation de mémoire et de désallocation, il est libre de faire à peu près tout ce qu'il veut. Ma compréhension est que la plupart des systèmes d'exploitation ont des tables d'allocation de mémoire différentes pour chaque processus, ils pourraient donc littéralement donner la même adresse de mémoire virtuelle à plusieurs programmes, mais ces adresses de mémoire seraient mappées à différents blocs réels en mémoire. Ainsi, un système d'exploitation 64 bits peut allouer le nombre maximal d'adresses 32 bits à plusieurs programmes 32 bits - ils ne sont pas tous limités aux mêmes adresses mémoire 32 bits.
Cependant, il existe des limites: le système d'exploitation peut avoir des limites définies à la taille à laquelle le fichier d'échange est autorisé à se développer. Donc, à moins que vous n'ayez délibérément demandé à votre système d'exploitation de le faire, il n'aura probablement pas 64 Go de mémoire virtuelle totale. Et même si c'était le cas, il ne peut pas allouer les 64 Go à chaque programme, vous auriez donc probablement une erreur OutOfMemory
avant que le système d'exploitation n'alloue une adresse virtuelle à 0xFFFFFFFFF
à votre programme. (En fait, je ne serais pas surpris d'apprendre que 0xFFFFFFFFF
est en fait un emplacement réservé de code d'erreur, semblable à 0x0
.) Mais étant donné que les adresses connues de votre programme n'ont aucune corrélation avec les vraies adresses mémoire, il est possible que vous finissiez par recevoir une adresse mémoire que votre programme considère comme 0xFFFFFFFFF
, même si le système d'exploitation n'utilise pas autant de mémoire.
Existe-t-il un grand tableau de pages géant qui inclut toutes les pages de chaque processus ou chaque processus a son propre tableau de pages?
Probablement les deux ... et puis certains.
Donc, en supposant qu'un processus a été alloué de la mémoire à l'adresse 0x00000002
, quand il va charger la valeur de cette adresse mémoire, le système d'exploitation pourrait reconnaître que cela correspond en fait à l'adresse mémoire réelle 0x00000F23
, et c'est l'adresse mémoire dont la valeur sera effectivement récupérée dans le registre CPU. Ou, il pourrait se rendre compte qu'il a déplacé la page contenant cette adresse sur le disque quelque part, auquel cas le système d'exploitation trouvera une partie vide de la mémoire et chargera d'abord les données de la page du disque dans cette mémoire. (Encore une fois, cette adresse mémoire n'a aucune corrélation avec l'adresse mémoire d'origine demandée par le programme.)
S'il n'y a pas de mémoire vide pour extraire la page, le système d'exploitation devra d'abord déplacer des données hors de la mémoire et dans le fichier d'échange. Il essaie de déterminer intelligemment quelle mémoire est la moins susceptible d'être utilisée dans un avenir proche. Mais parfois, vous vous retrouvez avec une mémoire constamment sollicitée peu de temps après son échange sur le disque, uniquement pour remplacer la prochaine mémoire qu'un programme était sur le point de demander. Ce "thrashing" est ce qui ralentit les ordinateurs avec une mémoire insuffisante vraiment, vraiment, car les accès au disque sont des ordres de grandeur plus lents que les accès à la mémoire.
Avant de répondre à vos questions (j'espère que oui), voici quelques remarques liminaires:
Le problème ici est que la "mémoire virtuelle" a deux sens. La "mémoire virtuelle" en tant que terme technique utilisé par les programmeurs de bas niveau n'a (presque) rien à voir avec la "mémoire virtuelle" comme expliqué aux consommateurs.
Au sens technique, la "mémoire virtuelle" est un système de gestion de la mémoire par lequel chaque processus a son propre espace d'adressage virtuel, et les adresses de mémoire dans cet espace d'adressage sont mappées à des adresses de mémoire physique par le noyau du système d'exploitation avec prise en charge matérielle (utilise des termes comme TLB, tableaux de pages à plusieurs niveaux, défauts de page et parcours, etc.). C'est le sens de VM qui vous intéresse (décrit ci-dessous).
Dans le sens non technique, la "mémoire virtuelle" est l'espace disque utilisé à la place de RAM (utilise des termes comme swap, backing store, etc.). C'est le sens de VM qui ne vous intéresse pas particulièrement, mais il semble que vous ayez vu du matériel qui traite principalement de ce sens du terme ou brouille les deux.
que se passe-t-il lorsque mes programmes souhaitent accéder à l'adresse mémoire 0xFFFFFFFFF? Je n'ai que 4 Go
Dans ce cas, votre "Théorie 1" est plus proche.
VM dissocie les adresses que votre programme "voit" et fonctionne avec - les adresses virtuelles - des adresses physiques. Votre 4GiB de mémoire peut être à physique adresses de 0x0 à 0xFFFFFFFF (8 F), mais l'adresse 0xFFFFFFFFF (9 F) est dans l'espace utilisateur (en disposition canonique) de virtuel adresses. À condition que 0xFFFFFFFFF soit dans un bloc alloué au processus, le CPU et le noyau (de concert) traduiront l'adresse de page 0xFFFFFF000 (en supposant une page de 4k, nous hackons juste les 12 bits inférieurs) en une vraie page physique, qui pourrait avoir (presque) n'importe quelle adresse de base physique. Supposons que l'adresse physique de cette page soit 0xeac000 (une relation établie lorsque le noyau vous a donné la page virtuelle 0xFFFFFF000), puis l'octet à l'adresse virtuelle 0xFFFFFFFFF est à l'adresse physique 0x00eacfff.
Lorsque vous déréférencez 0xFFFFFFFFF (en supposant 4 000 pages), le noyau "demande" au CPU d'accéder à cette adresse virtuelle, et le CPU coupe les 12 bits inférieurs, et recherche la page dans le dTLB (les tampons de côté de traduction sont virtuels à- caches physiques de mappage de pages; il y en a au moins un pour les données et un pour les instructions). S'il y a un hit, le CPU construit la véritable adresse physique et récupère la valeur. S'il y a un échec TLB, le CPU soulève une erreur de page, ce qui amène le noyau à consulter (ou "marcher") les tables de pages pour déterminer la bonne page physique, et "renvoie" cette valeur au CPU, qui la met en cache dans le dTLB (il est très probable qu'il soit réutilisé presque immédiatement). Le noyau demande alors au CPU cette adresse encore et cette fois, il réussira sans déclencher une marche.
J'avoue que cette description est assez minable (reflétant mon propre niveau de connaissance). En particulier, la façon exacte dont un processus particulier est identifié dans le TLB n'est pas à 100% claire pour moi et au moins quelque peu spécifique au matériel. Auparavant, chaque changement de contexte nécessitait un vidage TLB complet, mais les processeurs Intel plus récents ont un champ "PID" 6 bits, ce qui signifie que les vidages, même s'ils sont parfois requis, ne le sont pas toujours requis sur un changement de contexte. La grossièreté découle de mon incapacité à décrire les TLB à plusieurs niveaux, les PTE (entrées du tableau de pages) et à aborder l'importance de cela sur la mise en cache des données et des instructions (bien que je sache que le matériel moderne peut voir s'il est possible qu'une adresse soit dans un certain niveau de cache en même temps que la recherche TLB).
Comment les processus sont-ils placés dans la mémoire virtuelle? Je veux dire que chaque processus a-t-il de l'espace de mémoire virtuelle 0x0 - 0xFFFFFFFFF disponible pour eux ou qu'il n'y a qu'un seul espace d'adresse de mémoire virtuelle où tout le processus est placé?
Chaque processus a son propre espace de mémoire virtuelle complètement distinct. C'est (presque) tout l'intérêt de VM.
Autrefois, la TLB n'était en aucun cas "consciente du processus". Chaque changement de contexte signifiait que les TLB devaient être complètement vidés. De nos jours, les entrées TLB ont un court champ "contexte de processus" (PCID?) Et prennent en charge le rinçage sélectif, de sorte que vous pouvez le considérer comme le PID (ou, plutôt, le PCID: une sorte de hachage du PID) étant ajouté à l'adresse de la page virtuelle, donc le TLB est plus sensible aux processus, et seules ces entrées doivent être vidées en cas de collision PCID avec un autre processus (deux processus sont mappés sur le même PCID).
Existe-t-il un grand tableau de pages géant qui inclut toutes les pages de chaque processus ou chaque processus a son propre tableau de pages?
Ceci est spécifique au système d'exploitation, bien sûr, mais d'après ce que je comprends, Linux possède un ensemble à plusieurs niveaux de tables de pages où les entrées (PTE) sont étiquetées avec le PID, plutôt qu'il n'y ait des per- tables de pages de processus. I pensez la raison fondamentale de cela est que beaucoup de mappages virtuel-physique sont n: 1 plutôt que 1: 1, car tous étant 1: 1 déjouer en grande partie un objectif majeur de VM: pensez aux pages partagées en lecture seule contenant les instructions pour les bibliothèques comme libc
, ou aux pages de données de copie sur écriture partagées entre le parent et l'enfant après un fork. La duplication de ces entrées pour chaque processus dans des tables de pages par processus est moins efficace que l'ajout/la suppression des entrées spécifiques au processus vers/à partir d'un ensemble commun de tables de pages lorsqu'un processus est créé/quitte.
Une fois que vous avez un système VM, il devient presque trivial d'ajouter la possibilité de récupérer une page du disque en cas de défaillance d'une page et d'implémenter le "vieillissement" pour les PTE afin que les pages les moins récemment utilisées peut être placé sur le disque. Bien qu'il s'agisse d'une fonctionnalité importante sur les systèmes à mémoire limitée, elle est presque entièrement hors de propos pour comprendre comment un système VM fonctionne réellement).