2016-01-16 5 views
0

Dans le concept de mémoire virtuelle, la page physique est allouée uniquement lorsque la page correspondante est utilisée dans l'espace virtuel.Accès à la page non allouée

Je me demande quand une telle allocation a lieu.

J'ai essayé de référencer certaines adresses choisies au hasard, mais la plupart du temps, cela me donne un défaut de segmentation. Je suppose que la plupart des pages sont marquées comme non utilisables, et la simple lecture de la page ne suffit pas à forcer l'OS à m'attribuer un cadre de page physique. (J'ai essayé ceci avec GDB)

+0

_ ** Je me demande quand une telle allocation a lieu. ** _ Dans un appel de système d'exploitation. –

+0

Vous devez uniquement référencer la mémoire qui a été allouée par votre programme, soit dans le cadre d'un stockage statique ou automatique, soit à la suite d'un appel de fonction d'allocation dynamique. –

Répondre

0

L'OS s'occupera de ceci. Pour le voir en action, vous devrez instrument ou appliquer débogueur au code du noyau du système d'exploitation, mais le concept peut être vu par:

int *p = new int[1000000]; 

Cela affectera environ 4 Mo (1000 pages) de mémoire, mais jusqu'à présent aucun d'entre eux ont été utilisés, alors rien ne sera « physiquement affecté » (mais peut-être le premier a en fait, car il est susceptible d'être utilisée pour stocker les métadonnées pour l'attribution)

p[2048] = 42; 

maintenant, le système d'exploitation prendre une erreur de page pour 8192 octets dans l'allocation, et une fois que cela est terminé, la valeur 42 peut être écrite sur cette page.

L'exécution de GDB ne le montrera pas. En plus du fait qu'il est beaucoup plus lent que d'écrire sur une page physique déjà "validée", vous pouvez l'essayer en écrivant à un élément tous les 4K dans 100MB de données, ou les 250000 premières entrées dans les mêmes 100MB - puis en écrivant une deuxième fois. Les deux seront plus rapides la deuxième fois, mais grâce aux erreurs de page qui ne se produisent pas la deuxième fois, la deuxième fois dans le premier cas sera nettement plus rapide.

Un exemple:

#include <iostream> 
#include <chrono> 
#include <functional> 
#include <memory> 

void measure(const std::string& test, std::function<void()> function) 
{ 
    auto start_time = std::chrono::high_resolution_clock::now(); 

    function(); 

    auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - start_time); 
    std::cout<<test<<" "<<static_cast<double>(duration.count()) * 0.000001<<" ms"<<std::endl; 
} 

const int NWRITES = 1024*1024; 
const int PAGESTEP = 1024; 
const int NINTS = NWRITES*PAGESTEP; /* 1024M * sizeof(int) = 4GB */ 

int main() 
{ 
    std::unique_ptr<int[]> p(new int [NINTS]); 

    measure("Every int", [&p](){ for(int i = 0; i < NWRITES; i++) p[i] = i; }); 
    measure("Every 4KB", [&p](){ for(int i = 0; i < NWRITES; i++) p[i*PAGESTEP] = i; });  
    measure("Every int", [&p](){ for(int i = 0; i < NWRITES; i++) p[i] = i; }); 
measure("Every 4KB", [&p](){ for(int i = 0; i < NWRITES; i++) p[i*PAGESTEP] = i; }); 
} 

donne quelque chose comme ceci:

Every int 10.3651 ms 
Every 4KB 1856.2 ms 
Every int 2.4179 ms 
Every 4KB 84.1603 ms 
0

Les violations d'accès que vous décrivez sont le résultat de pages logiques ne pas être valide; pas le fait qu'ils n'ont pas été consultés. La création d'une page réelle en mémoire virtuelle nécessite plusieurs étapes d'allocation. Pour comprendre cela, vous devez diviser les concepts de la traduction de la mémoire logique et de la mémoire virtuelle. Une unité de gestion de mémoire présente un espace d'adressage logique contigu. Dans cet espace d'adressage, les pages peuvent ou non correspondre à des cadres de pages physiques. Bien que l'espace d'adressage puisse être contigu, la plage de pages valides n'est généralement pas contiguë.

L'unité de gestion de mémoire convertit les adresses logiques en adresses physiques à l'aide d'une PAGE PAGE.

Les processeurs utilisent généralement des tables de pages multiples ou des tables de pages imbriquées (une table référence une autre référence pour identifier le cadre de page). Dans le premier cas, la longueur de la table de page peut être plus courte que la plage complète d'adresses. Cela peut également être vrai pour ce dernier mais en plus, les tables de pages référençant des tables imbriquées (peuvent avoir des entrées nulles).

Cette structure de table de pages est créée avec le processus. Avoir une table de page ENTRY est une condition préalable pour avoir un mapping. Sur le système avec des tables de pages imbriquées, la taille de la table de pages peut être ajustée en ajoutant des entrées.La taille de la table est généralement limitée par les paramètres système ou les quotas de processus. (Ignorer le clonage Unix, les systèmes avec des shells persistants et les tables système) Au démarrage du processus, les entrées de la table de pages ne font référence à rien.

Le chargeur de programme effectue la configuration initiale du mappage de page. Ceci configure la table de page de sorte que le programme (tel que défini par le LINKER) ait des adresses valides dans la table de page.

Un cadre de page réel ne sera pas mappé à la page tant que vous n'y accéderez pas dans la plupart des cas. Cependant, vous ne le verrez pas dans vos applications. Si la table de pages indique que la page est valide et que vous faites référence à une page sans cadre physique, cela déclenche une erreur de page. Le système d'exploitation créera alors le mappage de cadre de page et redémarrera votre application. (Mémoire virtuelle)

Votre application peut mapper des pages supplémentaires lors de l'exécution. New et Malloc le font dans les coulisses, mais vous pouvez le faire directement. Lorsque vous créez de tels mappages, vous modifiez la table de pages afin qu'elle indique que la page logique est valide. Vous devez normalement ensuite référencer la page pour que le système d'exploitation mappe la page logique à un cadre de page physique. (En supposant que vous n'essayez pas d'écrire ou d'exécuter) En résumé, vous décrivez l'échec de la conversion de la mémoire logique en raison de l'absence d'entrée de table de pages valide pour les pages auxquelles vous essayez d'accéder.