Un sistema Unix-like, utilizza il meccanismo della memoria virtuale che consiste nell’assegnare ad ogni processo uno spazio di indirizzi di memoria (indirizzi che vanno da 0 ad un valore massimo - in genere 4 GiB). Tale spazio di indirizzi è virtuale, nel senso che tali indirizzi non corrispondono agli indirizzi fisici delle celle di memoria centrale. Si parla pertanto di memoria virtuale e questa è quella che “vede” un processo.
Come già accennato precedentemente, il kernel utilizza il meccanismo di paginazione della memoria (paging), ovvero suddivide la memoria in pagine di dimensione fissa (in genere 4 KiB). Ogni pagina di memoria virtuale viene quindi assegnata ad una pagina di memoria fisica, ma poiché la memoria centrale potrebbe non essere sufficiente a mappare la memoria virtuale assegnata ad ogni processo (in genere la memoria fisica è molto minore di quella virtuale), alcune pagine di memoria virtuale vengono mappate sulla memoria di massa. È necessario un meccanismo che carichi le pagine mappate sulla memoria di massa in memoria centrale e viceversa: lo swap. Quando un processo vuole accedere ad una pagina di memoria virtuale che fa riferimento ad una pagina che non risiede (in quel momento) in memoria centrale, si verifica un page fault, ovvero l’hardware di gestione della memoria (il controller) genera un’interrupt che fa passare il controllo del sistema al kernel, che sospende il processo corrente ed esegue le operazioni necessarie a caricare la relativa pagina in memoria centrale. Quindi il kernel fa ripartire l’esecuzione del processo dal punto in cui era stato interrotto. Dal punto di vista del processo, il meccanismo della gestione della memoria è completamente trasparente, ovvero per i processo stesso tutto avviene come se la memoria fisica fosse effettivamente quella a lui assegnata: la memoria virtuale. La differenza che si avverte è quella relativa ai tempi di esecuzione del processo che saranno nettamente superiori a quelli che si avrebbero avendo a disposizione la quantità di memoria fisica pari a quella della memoria virtuale assegnata al processo stesso34.
La stessa quantità di memoria centrale (o di massa) può fare da supporto a più pagine di memoria virtuale (appartenenti a processi diversi) in modo da minimizzare la quantità di memoria fisica utilizzata. Questo è possibile se le informazioni contenute in tali pagine non sono modificabili da nessun processo (come il codice da eseguire): per esempio il codice della routine per la visualizzazione di una stringa sullo schermo, utilizzato dai programmi scritti in C con la chiamata alla funzione printf, è contenuto in una zona della memoria fisica che farà da supporto a tutte le pagine di memoria virtuale dei vari processi che ne fanno uso.
Esiste anche la possibilità di bloccare il meccanismo di swap, mantenendo le le pagine in memoria centrale per il supporto delle opportune pagine virtuali, senza scaricarle sulla memoria di massa. Questo può essere necessario per processi particolari che necessitano che la velocità di esecuzione non subisca delle variazioni poco controllabili.
La memoria virtuale assegnata ad un processo è suddivisa in segmenti, ovvero in blocchi di indirizzi contigui. In genere un processo viene diviso nei seguenti segmenti (v. fig. 7.2):
Lo stack segment e lo heap segment fanno parte in realtà dello stesso segmento di memoria, soltanto che per l’heap viene utilizzata la zona con gli indirizzi inferiori mentre per lo stack viene utilizzata la zona con gli indirizzi superiori. Così l’heap cresce dal basso verso l’alto e lo stack dall’alto verso il basso. La parte effettivamente utilizzata per lo stack e per l’heap (inizialmente vuoti) varia dinamicamente durante l’esecuzione del programma, ma il segmento di memoria assegnato al processo per tali scopi è comunque fissato alla creazione dello stesso.
Sebbene l’intervallo degli indirizzi relativi alla memoria virtuale assegnata ad un processo sia molto ampio, solo una parte di tali indirizzi è effettivamente assegnato alla memoria centrale (allocato) e quindi utilizzabile dal processo stesso. Se un processo tenta di accedere ad un indirizo di memoria non allocato, si verifica un errore di violazione di segmento (o segmentation fault o segmentation violation).
La quantità di memoria (centrale + swap) libera e occupata sul sistema è visualizzabile con il comando free (man page free(1)), che si basa sul contenuto del file /proc/meminfo.
____________________________________________________________________
Comando: free
Path: /usr/bin/free
SINTASSI
$ free [option]
DESCRIZIONE
Le statistiche sulla gestione della memoria virtuale relativamente ai processi, al paging, all’attività della CPU, sono ottenibili con il comando vmstat (man page vmstat(8)).
__________________________________________________________________________________________________________
Comando: vmstat
Path: /usr/bin/vmstat
SINTASSI
$ vmstat [option]
DESCRIZIONE
[da completare ...];