La gestione della memoria in Linux: la memoria virtuale e la cache di buffer del disco.

Creato il 16 settembre 2010 da Linuxlandia
Questa sezione descrive le caratteristiche di gestione della memoria di Linux, cioè la memoria virtuale e la cache di buffer del disco. Ne vengono descritti lo scopo, il funzionamento e le azioni necessarie da parte dell'amministratore di sistema.

Cosa è la memoria virtuale?

Linux supporta la memoria virtuale, cioè l'utilizzo di un disco come estensione della RAM in modo da aumentare di conseguenza la dimensione della memoria utilizzabile. Il kernel scrive il contenuto di un blocco di memoria che al momento non viene utilizzato sull'hard disk, in modo che la memoria possa essere usata per altre cose, e quando il contenuto originale serve ancora viene spostato di nuovo nella RAM. Questo processo è completamente trasparente all'utente: i programmi che girano sotto Linux vedono soltanto una memoria disponibile più grande del vero e non sanno che parte di essa risiede sull'hard disk. Naturalmente leggere e scrivere sull'hard disk è più lento (dell'ordine di un migliaio di volte) che usare la memoria vera, quindi i programmi non sono ugualmente veloci. La parte dell'hard disk che viene usato come memoria virtuale si chiama spazio di swap.

Linux può usare come spazio di swap sia un file normale nel filesystem che una partizione separata; una partizione è più veloce, ma è più facile modificare la dimensione di un file (non c'è bisogno di ripartizionare l'intero hard disk e probabilmente installare tutto da zero). Quando sapete la quantità di spazio di swap di cui avete bisogno vi conviene usare una partizione, ma se non siete sicuri create un file, usate il sistema per un po' per farvi un'idea e poi fate una partizione quando siete sicuri sulla sua dimensione.

Dovreste anche sapere che Linux permette di usare diversi file e partizioni di swap nello stesso momento. Per questo, se vi serve per un periodo uno spazio di swap più grande del normale, potete impostare un file temporaneo, invece di tenerlo tutto sempre allocato.

Una nota sulla terminologia dei sistemi operativi: in informatica di solito si distingue tra lo swapping (scrivere tutto il processo nello spazio di swap) e il paging (scriverci solo delle parti di dimensione fissa, di solito alcuni kilobyte, alla volta). Il paging di solito è più efficiente, ed è quello che fa Linux, ma la terminologia tradizionale di Linux parla comunque di swapping

La creazione di uno spazio di swap.

Un file di swap è un file ordinario e non viene considerato in maniera speciale dal kernel. L'unica cosa che importa al kernel è che non deve avere buchi e che sia preparato all'uso con mkswap. Deve risiedere su un disco locale, comunque, e non può trovarsi su un filesystem montato via NFS per ragioni di implementazione.

La parte sui buchi è importante: il file riserva lo spazio disco in modo che il kernel possa fare velocemente lo swap di una pagina senza dover fare tutti i passi necessari per allocare un settore di un disco ad un file. Il kernel usa semplicemente i settori che sono stati allocati per il file; dato che un buco significa che per quel posto nel file non sono allocati settori, non è bene che il kernel provi ad usarli.

Un modo buono per creare il file di swap senza buchi è usando questo comando:

$ dd if=/dev/zero of=/extra-swap bs=1024 count=1024 1024+0 records in 1024+0 records out $
dove /extra-swap è il nome del file di swap e la sua dimensione viene data dopo count=. È meglio che la dimensione sia un multiplo di 4, perché il kernel manda in swap pagine di memoria di 4 kilobyte. Se la dimensione non è un multiplo di 4 l'ultimo paio di kilobyte può restare inutilizzato.

Anche una partizione di swap non è in nessun modo una partizione speciale: la si crea come una qualsiasi altra partizione, l'unica differenza è che viene usata così com'è e non contiene un filesystem. È una buona idea segnare le partizioni di swap come tipo 82 (Linux swap); in questo modo renderete più chiara la tabella delle partizioni, anche se non è strettamente necessario per il kernel.

Dopo aver creato un file o una partizione di swap bisogna scrivere al suo inizio una firma che contiene delle informazioni di amministrazione usate dal kernel. Il comando per farlo è mkswap, che si usa così:

$ mkswap /extra-swap 1024 Setting up swapspace, size = 1044480 bytes $
Notate che lo spazio di swap non è ancora in uso: esiste, ma il kernel non lo usa per fornire memoria virtuale.

Va fatta molta attenzione nell'usare mkswap, dato che questo non controlla che il file o la partizione non siano usati per altre cose. Potete facilmente sovrascrivere file e partizioni importanti! Per fortuna di solito si usa mkswap solo quando si installa il sistema.


Il gestore di memoria di Linux limita la dimensione di ciascuno spazio di swap a circa 127 MB (per varie ragioni tecniche, il limite reale è (4096-10) * 8 * 4096 = 133890048 byte, o 127.6875 megabyte). Potete comunque usare fino a 8 spazi di swap simultaneamente, per un totale di circa 1 GB

Come si usa lo spazio di swap.

Uno spazio di swap inizializzato si mette in uso con swapon, che comunica al kernel che può essere utilizzato. Come argomento viene dato il percorso per il file o la partizione, quindi per cominciare ad usare uno spazio di swap temporaneo si può fare:

$ swapon /extra-swap $

Gli spazi di swap possono essere usati automaticamente elencandoli nel file /etc/fstab.
/dev/hda8        none        swap        sw     0     0 /swapfile        none        swap        sw     0     0

Gli script di avvio fanno partire il comando swapon -a, che comincerà ad usare come swap tutti gli spazi elencati in /etc/fstab. Il comando swapon è quindi necessario solo se si usano spazi di swap supplementari.

Si può controllare l'utilizzo degli spazi di swap usando il comando free, che dice la quantità totale di spazio di swap usata.

$ free              total       used       free     shared    buffers Mem:         15152      14896        256      12404       2528 -/+ buffers:            12368       2784 Swap:        32452       6684      25768 $

La prima linea di output (Mem:) mostra la memoria fisica. La colonna total non considera la memoria fisica usata dal kernel, che in genere è circa un megabyte, used mostra la quantità di memoria usata (nella seconda linea non vengono contati i buffer), free quella totalmente inutilizzata e shared quella condivisa da diversi processi: più è, meglio è. La colonna buffer mostra la dimensione corrente della cache di buffer del disco.

L'ultima linea (Swap:) mostra le stesse informazioni per gli spazi di swap. Se questa linea contiene tutti zeri, non avete attivato lo spazio di swap.

Le stesse informazioni sono disponibili con top o usando il filesystem proc, in particolare il file /proc/meminfo. Al momento è difficile avere delle informazioni sull'uso di uno spazio di swap specifico.

Uno spazio di swap può essere disabilitato con swapoff; in genere non è necessario farlo, tranne che per gli spazi di swap temporanei. Le pagine in uso nello spazio di swap vengono per prima cosa copiate nella memoria; se non c'è memoria fisica sufficiente vengono messe in un altro spazio di swap. Se non c'è abbastanza memoria virtuale per mantenere tutte le pagine Linux comincerà a fare rumore; dopo un po' di tempo dovrebbe tornare normale, ma nel frattempo il sistema è inutilizzabile. Bisognerebbe sempre controllare (ad esempio con free) che ci sia abbastanza memoria libera prima di disabilitare uno spazio di swap.

Tutti gli spazi di swap che vengono usati automaticamente con swapon -a possono essere disabilitati usando swapoff -a, che va a guardare in /etc/fstab per vedere quali spazi rimuovere. Gli spazi di swap attivati manualmente rimarranno in uso.

Talvolta può venire usato spazio di swap anche se c'è molta memoria fisica libera; ad esempio se ad un certo punto c'è bisogno di fare swap, ma poi un processo grande che occupava molta memoria fisica termina e libera la memoria. I dati messi in swap non vengono reinseriti in memoria automaticamente, ma solo quando servono, quindi la memoria fisica può restare libera per parecchio tempo. Non c'è bisogno di preoccuparsene, ma può essere confortante sapere cosa sta succedendo.

La condivisione dello spazio di swap con altri sistemi operativi.

La memoria virtuale viene usata da molti sistemi operativi; dato che ne hanno bisogno solo mentre stanno funzionando, cioè mai allo stesso tempo, gli spazi di swap di tutti i sistemi operativi presenti meno uno vanno sprecati, e sarebbe più efficiente se condividessero un solo spazio di swap. È possibile, ma richiede un po' di impegno.

Allocare lo spazio di swap.

Alcuni vi diranno di allocare uno spazio di swap corrispondente al doppio della vostra memoria fisica, ma è una regola approssimativa. Ecco come fare in modo corretto:

  • Stimate di quanta memoria avete bisogno: calcolate la quantità più alta di memoria di cui avrete mai bisogno in una volta sola, cioè la somma del fabbisogno di tutti i programmi che volete far girare contemporaneamente: lo potete fare facendoli girare tutti insieme.

    Ad esempio, se volete usare X dovreste allocargli circa 8 MB, gcc vuole qualche megabyte (alcuni file hanno bisogno di moltissima memoria, fino a decine di megabyte, ma di solito quattro bastano) e così via. Il kernel userà per sé circa un megabyte, le normali shell ed altri programmi qualche centinaia di kilobyte (diciamo un megabyte tutti insieme). Non c'è bisogno di tentare di essere esatti, basta una stima rozza, magari per eccesso.

    Ricordatevi che se ci sono diverse persone che usano il sistema in contemporanea consumeranno tutti della memoria; comunque, se due persone usano lo stesso programma contemporaneamente l'utilizzo complessivo di memoria non è di solito doppio, dato che le pagine di codice e le librerie condivise vengono usate solo una volta.

    Per stimare le necessità di memoria sono utili i comandi free e ps.

  • Aggiungete per sicurezza un po' di memoria alla stima del passo 1: la dimensione di alcuni programmi sarà sbagliata, o forse vi dimenticherete alcuni programmi che volete usare ed è meglio avere un po' di spazio extra per qualsiasi evenienza. Un paio di megabyte dovrebbero andare bene (è meglio allocare troppo spazio di swap che troppo poco, ma non c'è bisogno di strafare e allocare l'intero disco, dato che lo spazio di swap inutilizzato è sprecato; vedi sopra come fare per aggiungere altro spazio). Inoltre, dato che si lavora meglio con le cifre tonde, arrotondate il valore al megabyte superiore.

  • Basandovi sul calcolo qui sopra sapete di quanta memoria avete bisogno in totale. Per allocare lo spazio di swap dovete dunque sottrarre la dimensione della memoria fisica dalla memoria totale (in alcune versioni di UNIX dovete allocare dello spazio di swap anche per un'immagine della memoria fisica, quindi il totale calcolato nel passo 2 è lo swap necessario e non dovete fare la sottrazione).

  • Se lo spazio di swap calcolato è molto più grande della memoria fisica (più del doppio) dovreste investire in più memoria fisica, o le prestazioni saranno troppo basse.

È una buona idea avere comunque dello spazio di swap, anche se i calcoli indicano che non ne avete bisogno; Linux lo usa in modo piuttosto aggressivo, in modo che possa essere tenuta libera più memoria fisica possibile, e manderà in swap delle pagine di memoria che non vengono usate anche se non c'è ancora bisogno di memoria per altre cose. Un comportamento del genere evita di aspettare di fare swap nel momento in cui ce n'è bisogno---si può fare prima, quando il disco altrimenti non sta lavorando. Lo spazio di swap può essere suddiviso tra vari dischi, in modo da poter in qualche modo migliorare le prestazioni, a seconda delle loro velocità e degli schemi di accesso. Potete fare degli esperimenti con schemi diversi, ma farlo in modo corretto non è semplice. Non credete a chi dice che uno schema è sicuramente superiore ad un altro, perché non sempre è vero.

La cache di buffer.

Leggere da un disco è molto più lento che accedere a della memoria (reale). Oltre a ciò, è comune leggere la stessa parte del disco diverse volte in brevi periodi di tempo. Ad esempio, si può prima leggere un messaggio di posta elettronica, poi caricare lo stesso messaggio in un editor per rispondere, poi farlo leggere al programma di posta per copiarlo in una cartella. Oppure, considerate quanto spesso si può usare il comando ls su un sistema con molti utenti. Leggendo le informazioni dal disco e trattenendole in memoria finché non servono più si possono velocizzare le letture successive alla prima. Questo processo si chiama bufferizzazione del disco, e la memoria usata allo scopo è la cache di buffer.

Dato che la memoria è, sfortunatamente, una risorsa finita, anzi, scarsa, la cache di buffer di solito non può essere abbastanza grande (non può contenere tutti i dati che si vogliono usare). Quando la cache si riempie, i dati che non sono stati usati per il tempo più lungo vengono scartati e la memoria liberata viene usata per quelli nuovi.

La bufferizzazione del disco vale anche in scrittura; da una parte i dati scritti vengono spessi letti di nuovo (come per un codice sorgente che viene salvato in un file, e poi letto dal compilatore), quindi mettere in cache i dati che vengono scritti è una buona idea; dall'altra, solo mettendo i dati nella cache e non scrivendoli nel disco, il programma che li scrive gira più veloce. La scrittura si può fare in background, senza rallentare gli altri programmi.

La maggior parte dei sistemi operativi usano le cache di buffer (anche se si possono chiamare in altri modi), ma non tutte funzionano con i principi descritti sopra. Alcune sono write-through: i dati vengono scritti tutti insieme nel disco (vengono mantenuti anche nella cache, naturalmente), mentre la cache si chiama write-back se la scrittura viene fatta in un secondo tempo. Il write-back è più efficiente del write-through, ma anche più soggetto ad errori: se la macchina ha un crash, viene tolta la corrente al momento sbagliato o il floppy viene rimosso dal drive prima che i dati nella cache vengano scritti, i cambiamenti nella cache vengono persi; ciò può anche comportare che il filesystem (se ce n'è uno) non sia pienamente funzionante, perché forse i dati non scritti contenevano cambiamenti importanti alle informazioni di archiviazione.

Per questo non dovreste mai spegnere il computer senza usare una corretta procedura di shutdown, rimuovere un floppy dal drive senza smontarlo (se era stato montato) o dopo che qualsiasi programma che lo stia usando abbia segnalato di aver finito e che il led del floppy non si sia spento. Il comando sync fa il flush del buffer, cioè forza la scrittura di tutti i dati nel disco, e può essere usato quando si vuole essere certi che tutto venga scritto al sicuro. Nei sistemi UNIX tradizionali c'è un programma chiamato update in background che fa un sync ogni 30 secondi, in modo che non è in genere necessario usare sync. Linux ha un daemon aggiuntivo, bdflush, che fa un sync più imperfetto con frequenza maggiore per evitare il blocco improvviso dovuto al pesante input/output del disco causato a volte da sync.

Sotto Linux bdflush viene avviato da update. Di solito non c'è ragione per preoccuparsene, ma se per qualche ragione bdflush muore il kernel vi avviserà e dovrete riavviarlo a mano (/sbin/update).

La cache in genere non fa il buffer dei file ma di blocchi, che sono le unità più piccole dell'input/output dei dischi (sotto Linux di solito sono di 1 kB). In questo modo vengono messe in cache anche le directory, i superblocchi, altri dati di archiviazione dei filesystem e dischi che contengono un filesystem.

L'efficacia di una cache è principalmente decisa dalla sua dimensione: una cache piccola è praticamente inutile, dato che conterrà talmente pochi dati che tutti i dati in cache vengono tolti prima di venir riutilizzati. La dimensione critica dipende da quanti dati vengono letti e scritti e da quanto spesso vengono riutilizzati gli stessi. L'unico modo di saperlo è sperimentare.

Se la cache è di dimensione fissa non è neanche bene che sia troppo grande, perché potrebbe rimpicciolire troppo la memoria libera e rendere necessario fare swap (che è ugualmente lento). Per usare in modo più efficiente possibile la memoria reale Linux usa automaticamente tutta la RAM libera per la cache di buffer, ma rimpicciolisce la cache automaticamente quando i programmi hanno bisogno di più memoria.

Sotto Linux non dovete fare niente per utilizzare la cache, che funziona completamente in automatico; dovete solo seguire le procedure corrette per fare shutdown e per rimuovere i floppy.


Se ti è piaciuto l'articolo , iscriviti al feed cliccando sull'immagine sottostante per tenerti sempre aggiornato sui nuovi contenuti del blog:



Potrebbero interessarti anche :

Possono interessarti anche questi articoli :