Aggiunte alcune note in piu` sulla memoria virtuale. Introdotto il non-linar
[gapil.git] / process.tex
index 1166f5119bb17c853af906249cc922a7b9cc1592..b572ee39f7525aefd751c268de92669612a78721 100644 (file)
@@ -233,15 +233,15 @@ normalmente un programma 
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=14cm]{img/proc_beginend}
+  \includegraphics[width=9cm]{img/proc_beginend}
   \caption{Schema dell'avvio e della conclusione di un programma.}
   \label{fig:proc_prog_start_stop}
 \end{figure}
 
 Si ricordi infine che un programma può anche essere interrotto dall'esterno
 attraverso l'uso di un segnale (modalità di conclusione non mostrata in
-fig.~\ref{fig:proc_prog_start_stop}); torneremo su questo aspetto in
-cap.~\ref{cha:signals}.
+fig.~\ref{fig:proc_prog_start_stop}); tratteremo nei dettagli i segnali e la
+loro gestione nel capitolo \ref{cha:signals}.
 
 
 
@@ -258,15 +258,16 @@ esecuzione, e le varie funzioni utilizzabili per la sua gestione.
 \subsection{I concetti generali}
 \label{sec:proc_mem_gen}
 
-Ci sono vari modi in cui i vari sistemi organizzano la memoria (ed i dettagli
-di basso livello dipendono spesso in maniera diretta dall'architettura
-dell'hardware), ma quello più tipico, usato dai sistemi unix-like come Linux è
-la cosiddetta \textsl{memoria virtuale}\index{memoria~virtuale} che consiste
-nell'assegnare ad ogni processo uno spazio virtuale di indirizzamento lineare,
-in cui gli indirizzi vanno da zero ad un qualche valore massimo.\footnote{nel
-  caso di Linux fino al kernel 2.2 detto massimo era, per macchine a 32bit, di
-  2Gb. Con il kernel 2.4 ed il supporto per la \textit{high-memory} il limite
-  è stato esteso anche per macchine a 32 bit.}
+Ci sono vari modi in cui i sistemi operativi organizzano la memoria, ed i
+dettagli di basso livello dipendono spesso in maniera diretta
+dall'architettura dell'hardware, ma quello più tipico, usato dai sistemi
+unix-like come Linux è la cosiddetta \textsl{memoria
+  virtuale}\index{memoria~virtuale} che consiste nell'assegnare ad ogni
+processo uno spazio virtuale di indirizzamento lineare, in cui gli indirizzi
+vanno da zero ad un qualche valore massimo.\footnote{nel caso di Linux fino al
+  kernel 2.2 detto massimo era, per macchine a 32bit, di 2Gb. Con il kernel
+  2.4 ed il supporto per la \textit{high-memory} il limite è stato esteso
+  anche per macchine a 32 bit.}
 
 Come accennato in cap.~\ref{cha:intro_unix} questo spazio di indirizzi è
 virtuale e non corrisponde all'effettiva posizione dei dati nella RAM del
@@ -274,41 +275,46 @@ computer; in genere detto spazio non 
 indirizzi possibili sono utilizzabili, e quelli usabili non sono
 necessariamente adiacenti).
 
-Per la gestione da parte del kernel la memoria virtuale viene divisa in pagine
-di dimensione fissa (che ad esempio sono di 4kb su macchine a 32 bit e 8kb
-sulle alpha, valori strettamente connessi all'hardware di gestione della
-memoria),\footnote{con le versioni più recenti del kernel è possibile anche
-  utilizzare pagine di dimensioni maggiori, per sistemi con grandi
-  quantitativi di memoria in cui l'uso di pagine troppo piccole comporta una
-  perdita di prestazioni.} e ciascuna pagina della memoria virtuale è
-associata ad un supporto che può essere una pagina di memoria reale o ad un
-dispositivo di stoccaggio secondario (in genere lo spazio disco riservato alla
-swap, o i file che contengono il codice).
-
-Lo stesso pezzo di memoria reale (o di spazio disco) può fare da supporto a
-diverse pagine di memoria virtuale appartenenti a processi diversi (come
-accade in genere per le pagine che contengono il codice delle librerie
-condivise). Ad esempio il codice della funzione \func{printf} starà su una
-sola pagina di memoria reale che farà da supporto a tutte le pagine di memoria
-virtuale di tutti i processi che hanno detta funzione nel loro codice.
-
-La corrispondenza fra le pagine della \index{memoria~virtuale}memoria virtuale
-e quelle della memoria fisica della macchina viene gestita in maniera
-trasparente dal kernel con l'ausilio dell'hardware di gestione della memoria
-(la \textit{Memory Management Unit} del processore).  Poiché in genere la
-memoria fisica è solo una piccola frazione della memoria virtuale, è
-necessario un meccanismo che permetta di trasferire le pagine che servono dal
-supporto su cui si trovano in memoria, eliminando quelle che non servono.
-Questo meccanismo è detto \textsl{paginazione}\index{paginazione} (o
-\textit{paging}), ed è uno dei compiti principali del kernel.
+Per la gestione da parte del kernel la memoria viene divisa in pagine di
+dimensione fissa,\footnote{inizialmente questi erano di 4kb sulle macchine a
+  32 bit e di 8kb sulle alpha, con le versioni più recenti del kernel è
+  possibile anche utilizzare pagine di dimensioni maggiori (4Mb), per sistemi
+  con grandi quantitativi di memoria in cui l'uso di pagine troppo piccole
+  comporta una perdita di prestazioni.} e ciascuna pagina nello spazio di
+indirizzi virtuale è associata ad un supporto che può essere una pagina di
+memoria reale o ad un dispositivo di stoccaggio secondario (come lo spazio
+disco riservato alla swap, o i file che contengono il codice). Per ciasun
+processo il kernel si cura di mantenere un mappa di queste corrispondenze
+nella cosiddetta \itindex{page~table}\textit{page table}.\footnote{questa è
+  una semplificazione brutale, il meccanismo è molto più complesso; una buona
+  trattazione di come Linux gestisce la memoria virtuale si trova su
+  \cite{LinVM}.}
+
+Una stessa pagina di memoria reale può fare da supporto a diverse pagine di
+memoria virtuale appartenenti a processi diversi (come accade in genere per le
+pagine che contengono il codice delle librerie condivise). Ad esempio il
+codice della funzione \func{printf} starà su una sola pagina di memoria reale
+che farà da supporto a tutte le pagine di memoria virtuale di tutti i processi
+che hanno detta funzione nel loro codice.
+
+La corrispondenza fra le pagine della \index{memoria~virtuale} memoria
+virtuale di un processo e quelle della memoria fisica della macchina viene
+gestita in maniera trasparente dal kernel.\footnote{in genere con l'ausilio
+  dell'hardware di gestione della memoria (la \textit{Memory Management Unit}
+  del processore), con i kernel della serie 2.6 è comunque diventato possibile
+  utilizzare Linux anche su architetture che non dispongono di una MMU.}
+Poiché in genere la memoria fisica è solo una piccola frazione della memoria
+virtuale, è necessario un meccanismo che permetta di trasferire le pagine che
+servono dal supporto su cui si trovano in memoria, eliminando quelle che non
+servono.  Questo meccanismo è detto \textsl{paginazione} \index{paginazione}
+(o \textit{paging}), ed è uno dei compiti principali del kernel.
 
 Quando un processo cerca di accedere ad una pagina che non è nella memoria
-reale, avviene quello che viene chiamato un \textit{page
-  fault}\itindex{page~fault}; la gestione della memoria genera un'interruzione
-e passa il controllo al kernel il quale sospende il processo e si incarica di
-mettere in RAM la pagina richiesta (effettuando tutte le operazioni necessarie
-per reperire lo spazio necessario), per poi restituire il controllo al
-processo.
+reale, avviene quello che viene chiamato un \itindex{page~fault} \textit{page
+  fault}; la gestione della memoria genera un'interruzione e passa il
+controllo al kernel il quale sospende il processo e si incarica di mettere in
+RAM la pagina richiesta (effettuando tutte le operazioni necessarie per
+reperire lo spazio necessario), per poi restituire il controllo al processo.
 
 Dal punto di vista di un processo questo meccanismo è completamente
 trasparente, e tutto avviene come se tutte le pagine fossero sempre
@@ -320,7 +326,9 @@ Normalmente questo 
 in genere il sistema è molto efficiente in questo lavoro; quando però ci siano
 esigenze specifiche di prestazioni è possibile usare delle funzioni che
 permettono di bloccare il meccanismo della paginazione\index{paginazione} e
-mantenere fisse delle pagine in memoria (vedi sez.~\ref{sec:proc_mem_lock}).
+mantenere fisse delle pagine in memoria (vedi
+sez.~\ref{sec:proc_mem_lock}). Inoltre per certe applicazioni gli algoritmi di
+gestione della memoria 
 
 
 \subsection{La struttura della memoria di un processo}
@@ -332,12 +340,12 @@ tentativo di accedere ad un indirizzo non allocato 
 commette quando si è manipolato male un puntatore e genera quello che viene
 chiamato un \textit{segmentation fault}. Se si tenta cioè di leggere o
 scrivere da un indirizzo per il quale non esiste un'associazione della pagina
-virtuale, il kernel risponde al relativo \textit{page
-  fault}\itindex{page~fault} mandando un segnale \const{SIGSEGV} al processo,
-che normalmente ne causa la terminazione immediata.
+virtuale, il kernel risponde al relativo \itindex{page~fault} \textit{page
+  fault} mandando un segnale \const{SIGSEGV} al processo, che normalmente ne
+causa la terminazione immediata.
 
 È pertanto importante capire come viene strutturata \textsl{la memoria
-  virtuale}\index{memoria~virtuale} di un processo. Essa viene divisa in
+  virtuale} \index{memoria~virtuale} di un processo. Essa viene divisa in
 \textsl{segmenti}, cioè un insieme contiguo di indirizzi virtuali ai quali il
 processo può accedere.  Solitamente un programma C viene suddiviso nei
 seguenti segmenti:
@@ -418,9 +426,9 @@ caricamento del programma.
 \subsection{Allocazione della memoria per i programmi C}
 \label{sec:proc_mem_alloc}
 
-Il C supporta, a livello di linguaggio, soltanto due modalità di allocazione
-della memoria: l'\textsl{allocazione statica} e l'\textsl{allocazione
-  automatica}.
+Il C supporta direttamente, come linguaggio di programmazione, soltanto due
+modalità di allocazione della memoria: l'\textsl{allocazione statica} e
+l'\textsl{allocazione automatica}.
 
 L'\textsl{allocazione statica} è quella con cui sono memorizzate le variabili
 globali e le variabili statiche, cioè le variabili il cui valore deve essere
@@ -444,10 +452,12 @@ Il C non consente di usare variabili allocate dinamicamente, non 
 cioè definire in fase di programmazione una variabile le cui dimensioni
 possano essere modificate durante l'esecuzione del programma. Per questo le
 librerie del C forniscono una serie opportuna di funzioni per eseguire
-l'allocazione dinamica di memoria (in genere nello heap). Le variabili il
-cui contenuto è allocato in questo modo non potranno essere usate direttamente
-come le altre, ma l'accesso sarà possibile solo in maniera indiretta,
-attraverso dei puntatori.
+l'allocazione dinamica di memoria (in genere nello heap). 
+
+Le variabili il cui contenuto è allocato in questo modo non potranno essere
+usate direttamente come le altre, ma l'accesso sarà possibile solo in maniera
+indiretta, attraverso i puntatori alla memoria loro riservata che si sono
+ottenuti dalle funzioni di allocazione.
 
 
 \subsection{Le funzioni \func{malloc}, \func{calloc}, \func{realloc} e