+Si ricordi infine che un programma può anche essere interrotto dall'esterno
+attraverso l'uso di un segnale (modalità di conclusione non mostrata in
+\curfig); torneremo su questo aspetto in \secref{cha:signals}.
+
+
+
+\section{I processi e l'uso della memoria}
+\label{sec:proc_memory}
+
+Una delle risorse base che ciascun processo ha a disposizione è la memoria, ed
+uno degli aspetti più complessi di un sistema unix (ed in particolar modo di
+Linux) è appunto la gestione della memoria. Qui ci occuperemo però di come la
+memoria viene vista dal punto di vista di un programma in esecuzione in un
+processo.
+
+
+\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 in maniera diretta dall'architettura
+dell'hardware), ma quello più tipico, usato da unix (e da Linux) è quello di
+assegnare ad ogni processo uno spazio virtuale di indirizzamento lineare in
+cui gli indirizzi vanno da zero ad un qualche valore massimo (nel caso di
+Linux fino al kernel 2.2 detto massimo era per macchine a 32bit di 2Gb, con il
+kernel 2.4 il limite è stato esteso).
+
+Come accennato nell'introduzione questo spazio di indirizzi è virtuale e non
+corrisponde all'effettiva posizione dei dati nella RAM del computer; in genere
+detto spazio non è neanche continuo (cioè non tutti gli indirizzi sono
+utilizzabili e/o utilizzati).
+
+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), 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 hanno detta funzione nel loro codice.
+
+La corrispondenza fra le pagine della memoria virtuale e quelle della memoria
+fisica della macchina viene gestita in maniera trasparente dall'hardware di
+gestione della memoria (la \textit{Memory Management Unit} del processore),
+ma poiché in genere quest'ultima è solo una piccola frazione della memoria
+virtuale è necessario un meccanismo che permetta di trasferire le pagine
+virtuali che servono dal supporto su cui si trovano in memoria, eliminando
+quelle che non servono. Questo meccanismo è detto \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}; l'hardware di
+gestione della memoria (la MMU del processore) genera una 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 disponibili
+in memoria. L'unica differenza avvertibile è quella dei tempi di esecuzione,
+che passano dai pochi nanosecondi necessari per l'accesso a tempi molto più
+lunghi, dovuti all'intervento del kernel. Normalmente questo è il prezzo da
+pagare per avere un multitasking reale, ed 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 del paging e mantenere fisse delle pagine in memoria (vedi
+\ref{sec:proc_mem_lock}).
+
+
+\subsection{La struttura della memoria di un processo}
+\label{sec:proc_mem_layout}
+
+Benché lo spazio di indirizzi virtuali copra un intervallo molto ampio, solo
+una parte di essi è effettivamente allocato ed utilizzabile dal processo; il
+tentativo di accedere ad un indirizzo non allocato è un tipico errore che si
+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 una associazione della pagina
+virtuale il kernel risponde al relativo \textit{page fault}, mandando un
+segnale \macro{SIGSEGV} al processo, che normalmente ne causa la terminazione
+immediata.
+
+È pertanto importante capire come viene strutturata la 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:
+
+\begin{enumerate}
+\item Il segmento di testo (\textit{text segment}). Contiene il codice
+ macchina del programma e le costanti statiche. Normalmente viene condiviso,
+ in modo che più processi (anche diversi nel caso di librerie) possano
+ utilizzarlo, e viene marcato in sola lettura per evitare sovrascritture
+ accidentali (o maliziose) che ne modifichino le istruzioni.
+
+ Viene allocato da \func{exec} all'avvio del programma e resta invariato
+ per tutto il tempo dell'esecuzione.
+
+\item Il segmento dei dati (\textit{data segment}). Contiene le variabili
+ globali (cioè quelle definite al di fuori di tutte le funzioni). Di norma è
+ diviso in due parti.
+
+ La prima parte è il segmento dei dati inizializzati, che contiene le
+ variabili globali il cui valore è stato assegnato esplicitamente. Ad esempio
+ se si definisce:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+ double pi = 3.14;
+\end{lstlisting}
+ questo valore sarà immagazzinato in questo segmento. La memoria di questo
+ segmento viene preallocato dalla \func{exec} e inizializzata ai valori
+ specificati.
+
+ La seconda parte è il segmento dei dati non inizializzati, che contiene le
+ variabili globali il cui valore è stato non è assegnato esplicitamente. Ad
+ esempio se si definisce:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+ int vect[100];
+\end{lstlisting}
+ questo valore sarà immagazzinato in questo segmento. Anch'esso viene
+ allocato all'avvio, e tutte le variabili vengono inizializzate a
+ zero (ed i puntatori a \macro{NULL}).
+
+ Storicamente questo segmento viene chiamato BBS (da \textit{block started by
+ symbol}. La sua dimensione è fissa.
+
+\item Lo \textit{heap}. Tecnicamente lo si può considerare l'estensione del
+ segmento dati, a cui di solito è posto giusto di seguito. È qui che avviene
+ l'allocazione dinamica della memoria; può essere ridimensionato allocando e
+ disallocando la memoria dinamica con le apposite funzioni (vedi
+ \secref{sec:proc_mem_alloc}), ma il suo limite inferiore (quello adiacente
+ al segmento dati) ha una posizione fissa.
+
+\item Il segmento di \textit{stack}, che contiene lo \textit{stack} del
+ programma. Tutte le volte che si effettua una chiamata ad una funzione è
+ qui che viene salvato l'indirizzo di ritorno e le informazioni dello stato
+ del chiamante (tipo il contenuto di alcuni registri della CPU); poi la
+ funzione chiamata alloca qui lo spazio per le sue variabili locali, in
+ questo modo le funzioni possono essere chiamate ricorsivamente. Al ritorno
+ della funzione lo spazio è automaticamente rilasciato.
+
+ La dimensione di questo segmento aumenta seguendo la crescita dello stack
+ del programma, ma non viene ridotta quando quest'ultimo si restringe.
+\end{enumerate}
+
+\begin{figure}[htb]
+ \centering
+ \includegraphics[width=5cm]{img/memory_layout.eps}
+ \caption{Disposizione tipica dei segmenti di memoria di un processo}
+ \label{fig:proc_mem_layout}
+\end{figure}