Compago

...free knowledge

 
  • Increase font size
  • Default font size
  • Decrease font size
Home Manuali Windows La memoria virtuale dei processi di Windows

La memoria virtuale dei processi di Windows

E-mail Stampa PDF
Introduzione
Il paging
Gestione delle Page Tables
Protezione della memoria
Layout della memoria virtuale


Introduzione
I sistemi Windows a 32 bit x86 possono utilizzare al massimo 4GB di memoria fisica. Questo è dovuto al fatto che il bus di indirizzamento del processore, che è di 32 bit, può accedere ad un range di indirizzi che va dal 0x00000000 al 0xFFFFFFFF che rappresentano uno spazio di 4GB.
Windows permette ad ogni processo di avere i propri 4GB di memoria logica. I primi 2GB di questo spazio sono utilizzati per lo user mode , mentre gli altri 2GB sono riservati per il Windows Kernel mode.
Naturalmente si parla di memoria logica e non di memoria fisica, infatti io posso avere 1GB di RAM ed eseguire molti processi contemporaneamente. Questo è possibile grazie al paging che i sistemi Windows utilizzano.
Il paging consente al software di accedere alla memoria usando indirizzi logici che poi vendono tradotti in indirizzi fisici (RAM + hard disk) in maniera trasparente. In questo modo tutti i processi avranno i loro 4GB di spazio di indirizzamento logico.

Il paging nei processori x86

Il processore x86 divide lo spazio di indirizzamento fisico (memoria fisica) in pagine da 4KB ciascuna. Quindi per avere 4GB di memoria avremo bisogno di 1M (1024x1024) di 4KB pagine. Per fare questo viene usata una struttura a 2 livelli.
Il primo livello è la Page Directory mentre il secondo è rappresentato dalla Page Table
Quindi avremo una prima tabella, la Page Directory(PD), composta da 1024 elementi,e ognuna di queste punta ad una Page Table(PT) che contiene, a sua volta,1024 elementi i quali puntano alle pagine (quelle da 4KB).
Graficamente avremo una PD e 1024 PT:


Ogni elemento della Page Directory (Page Directory Entry o PDE) è di 4 bytes e punta alla Page Table. In modo analogo ogni elemento della Page Table (Page Table Entry o PTE) è di 4 bytes e punta all'indirizzo fisico delle pagine da 4KB. Per conservare 1024 Page Tables ognuna contenente 1024 PTE abbiamo bisogno di 4x1024x1024 bytes (4MB) di memoria, più i 4KB della Page Directory (4x1024).
Riassumento per suddividere 4GB di memoria in pagine da 4 KB, abbiamo bisogno di circa 4 Mega bytes di memoria.

Ora in queste tabelle però noi abbiamo molto più di quello che ci serve, infatti se prendiamo in considerazione la Page Directory questa deve contenere 1024 elementi (210) per cui sarebbero sufficienti degli elementi a 10 bit non a 32, stesso discorso vale per la Page Table. Quindi a che servono gli altri bit in ciascun elemento?
La risposta è semplice, essi vengono utilizzati per conservare delle informazioni sulla parte di memoria che vanno ad puntare, insomma sono dei suoi attributi.

Un indirizzo lineare o virtuale sarà composto da 10 bit dovuti al PDE(page directory entry) più 10 del PTE(page table entry) e i restanti 12 rappresenteranno l'offset all'interno della page (212 = 4096 = 4KB)

Indirizzo lineare (32 bit)
PDE
[31-22] 10bit
PTE
[21-12] 10bit
Offset
[11-00] 12bit

L'insieme del PDE e del PTE è anche chiamato PFN ovvero Page Frame Number.
Il PDE, cioè i bit dal 22esimo al 31esimo dell' indirizzo lineare,  rappresenta un indice della Page Directory, ad esempio se ci fosse 001100100 sarebbe il centesimo elemento della page directory. La page directory nel suo centesimo elemento avrà l'indirizzo della relativa Page Table.
I bit dal 21esimo al 12esimo dell'indirizzo lineare invece sono il PTE, che rappresenta l'indice di un elemento della Page Table che era stata identificata al passo precedente, quindi se avessimo il PTE = 0000001110 dovremo considerare il 14esimo elemento della page table, che al suo interno contiene l'indirizzo della page da 4KB nella memoria fisica.
I primi 12 bit dell'indirizzo lineare invece andranno ad indicare la cella di memoria all'interno della page, ovvero l'offset ( posizione relativa) rispetto all'inizio di quest'ultima.

Traduzione di un indirizzo lineare o virtuale ad indirizzo fisico


Come Windows gestisce la Page Table
Con windows ogni processo ha la sua Page Directory e le sue Page Tables. Quindi windows alloca 4 MB di spazio per ogni processo al fine di conservare le informazioni in queste tabelle.
Quando un processo viene creato, ogni elemento nella Page Directory contiene l'indirizzo fisico di una Page Table. Gli elementi nella page table possono essere validi o non-validi. Gli elementi validi contengono l'indirizzo fisico della pagina di memoria da 4KB allocata per essere usata dal processo.
Un elemento della PT non-valido invece contiene invece alcuni bit speciali che lo identificano come non-valido , questi sono anche noti come Invalid PTEs1.
A questo punto è bene sottolineare che il processo non saprà mai nulla della memoria fisica, cioè non saprà se sta leggendo o scrivendo su RAM o su disco, ne tantomeno gli indirizzi fisici, quelli che invece vedrà sono solamente gli indirizzi virtuali e quindi avrà a che fare solo con la sua memoria virtuale.
Tutti i dettagli che riguardano la memoria fisica sono gestiti dal Windows Memory manager e dal processore.
L'indirizzo dove risiede fisicamente la page directory del processo è chiamato Page Directory Base address (PDB). Questo valore nel momento in cui il processore si occupa del processo viene caricato in un registro speciale della CPU chiamato CR3 (su x86). Cambiando processo windows caricherà un nuovo valore nel CR3 che indicherà il Page Directory Base del nuovo processo.
In questo modo ogni processo potrà usufruire di un suo spazio di memoria virtuale (4G).
Questo tipo di memoria viene chiamato spazio di indirizzamento virtuale perché anche se il processo ha a disposizione l'intero spazio di 4GB esso potrà utilizzare solo la memoria virtuale che gli è stata assegnata; se tentasse di accedere alla memoria non allocata causerebbe una violazione, perché nella PTE quella memoria era stata contrassegnata come non valida e anche perché lo spazio virtuale di un processo non potrà mai puntare alla memoria fisica allocata da un altro processo, a meno che i processi non stiano usando una qualche specie di memoria condivisa.


Memory Protection

Con la gestione della memoria virtuale Windows fornisce un sistema sicuro per proteggere la memoria usata dai processi. Questo perché windows permette l'accesso solo alle parti di memoria fisica allocate, cioè inserite nella PTE, per il processo. Ogni accesso da parte dello stesso processo a parti non allocate, o il tentativo da parte di un altro processo di accedere ad una area di memoria precedentemente allocata causerebbe una violazione e quindi un errore.
Ora a dirla tutta non è che queste cose non si possano fare, ma per farle bisogna avere le necessarie autorizzazioni e comunque usare delle funzioni del kernel, quindi l'accesso sarebbe indiretto.
Per proteggere le informazioni contenute nelle PTE (page table entry) windows le conserva nello spazio di memoria del kernel, cioè nei 2GB dei quattro a disposizione che il sistema operativo assegna al kernel come abbiamo già detto in precedenza.
In questo modo il processo non potrà mai direttamente accedere o modificare le Page Tables. Naturalmente se si opera in kernel mode questo sarà possibile, perché questo vuol dire che siamo virtualmente i padroni dell'intero sistema.


Layout della memoria virtuale
Windows assegna i primi 2GB (o 3GB dipende dalle opzioni specificate nel file boot.ini) di memoria virtuale per lo user mode del processo e i restanti 2GB (o 1GB sempre in relazione ai parametri di avvio nel file boot.ini) per il kernel di Windows.
Nella memoria riservata al kernel, per la precisione dall'indirizzo 0xC0000000 al 0xC03FFFFF, sono conservate le Page Tables e la Page Directory.
Tutti i processi hanno le loro Page Tables memorizzate a partire dall'indirizzo 0xC0000000 e la page directory all'indirizzo 0xC0300000.

Memoria virtuale
0x00000000 2GB User mode
.
0x7FFFFFFF
0x80000000 2G Kernel mode
.
0xC0000000 4MB Page Tables
.
0xC03FFFFF
0xC0400000 4K Page Directory
.
0xC0400FFF
.
0xFFFFFFFF



I 1024 indirizzi a partire dal 0xC0300000 rappresentano i Page Directory Entry (PDE). Ogni PDE è di 4 byte e rappresenta l'indirizzo fisico di una Page Table.Ogni Page Table ha 1024 elementi che contengono l'indirizzo fisico della pagine di memoria da 4KB o contengono una invalid entry.
Questo era stato già spiegato nel paragrafo riguardante il paging di windows, ma è sempre meglio ripeterlo per chiarezza.
Come mai windows usa proprio l'indirizzo 0xC000000000 per memorizzare le Page Tables e l'indirizzo 0xC0400000 per la page directory?
Il motivo è molto semplice, sicuramente dovevano stare nella memoria riservata al kernel quindo oltre i primi 2GB, e poi dato che come opzioni di avvio del sistema operativo possiamo scegliere la grandezza della memoria virtuale assegnata allo user mode dei processi, specificando nel boot.ini l'opzione "/3GB", la posizione di queste tabelle vitali per la gestione della memoria dovevano risiedere dopo i 3GB. Infatti se controlliamo gli indirizzo base delle Page Tables, ci accorgeremo che 0xC000000000 = 3.221.225.472 bytes è proprio 3GB. Quindi le tabelle con la memoria gestita in modalità 2GB+2GB oppure 3GB+1GB non influirà sulla posizione delle tabelle che saranno sempre al sicuro nella memoria virtuale del kernel.

Vediamo un esempio pratico. Diciamo che vogliamo tradurre un indirizzo virtuale 0x0012f980 in un indirizzo fisico. Il precedente valore esadecimale 0x0012f980 in binario sarebbe:

00000000 00010010 11111001 10000000

Identifichiamo le sue componenti:

    PDE       PTE         Page
index index offset
0000000000
0100101111 100110000000
0x00 0x12F 0x980

Ora come prima cosa dovremo calcolarci l'indirizzo della Page Table utilizzando le informazioni a nostra disposizione, in particolare la formula è questa:

PTE address = PTE_BASE + (page directory index) * PAGE_SIZE
                + (page table index) * dimensione Page
              =   0xc0000000
                + 0x0   * 0x1000
                + 0x12F * 4
              =   0xC00004BC

Il primo parametro è il PTE_BASE che nella maggior parte dei sistemi (quelli non PAE) abbiamo detto essere l'indirizzo 0xC0000000 ; l'indice della Page Directory invece lo prendiamo dall'indirizzo virtuale di partenza ed è 0; la dimensione delle pagine è di 4096byte cioè in esadecimale 0x1000 ; l'indice della Page Table lo ricaviamo sempre dall'indirizzo virtuale ed è 0x12F; la dimensione delle pagine è di 4096byte cioè in esadecimale 0x1000 ; la dimensione di un elemento PTE è 4 byte, quindi:

PTE address = PTE_BASE + (page directory index) * PAGE_SIZE
                + (page table index) * dimensione elemento PTE
            = 0xc0000000 + 0x0 * 0x1000
                + 0x12F * 4
              =   0xC00004BC

Ora anche questo è un indirizzo virtuale, quindi il sistema per accedervi dovrà convertirlo in indirizzo fisico usando il valore conservato in CR3 e utilizzando l'indice della Page Directory. Noi per semplicità, magari con l'aiuto di un kernel debugger, diciamo che siamo riusciti ad esaminarne il contenuto che sarà il valore 0x09DE9067.
Questo valore è un elemento PTE ed è composto da 2 parti, la prima (i primi 12 bit) sono i flag status , ovvero dei bit che ci indicano gli attrubuti della pagina di memoria a cui questo elemento punta, mentre la seconda parte (gli ultimi 20 bit) sono il Page Frame Number (PFN).

Flag status = 0x067 = 000001100111
PFN = 0x09DE9 = 00001001110111101001

Bene l'indirizzo fisico dell'inizio della pagina sarà appunto questo PFN moltiplicato per la dimensione della pagina:

Indirizzo fisico pagina = PFN * dimensione pagina 
= 0x09DE9 * 0x1000 = 0x09DE9000

Ora per avere l'esatto indirizzo fisico dell'indirizzo virtuale iniziale dobbiamo solamente applicare l'offset che troviamo in quest'ultimo

Indirizzo fisico = 0x09DE9000 + 0x980 = 0x09DE9980

Una cosa importante da capire e che mentre ogni processo ha i suoi 2 GByte di user space memory, i restanti 2 GByte assegnati al suo kernel mode sono sempre in comune con gli altri processi. questo avviene grazie alla struttura delle page directory e delle page table, come mostrato nella immagine successiva.

Gli elementi della page directory di processo con indice maggiore o uguale a 512 puntano non alla page table di processo, bensì ad una page table di sistema, la quale è unica per tutti i processi.

 

Ultimo aggiornamento ( Giovedì 08 Ottobre 2009 08:27 )