+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 (che ad esempio sono di 4kb su
+macchine a 32 bit e 8kb sulle alpha, valori strettamente connessi all'hardware
+di gestione della memoria) di dimensione fissa, e ciascuna pagina della
+memoria virtuale è associata ad un supporto che può essere una pagina di
+memoria reale o ad un dipositivo 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 fuzione \texttt{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 (dalla \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. Normalemente 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}, si tenta cioè di leggere e scrivere
+da un indirizzo per il quale non esiste una associazione della pagina virtuale
+ed il kernel riponde al relativo \textit{page fault} mandando un segnale
+\texttt{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. Storicamente 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. Normalente viene condiviso
+ così che più processi (anche diversi nel caso di librerie) possano
+ utilizzarlo e marcato in sola lettura per evitare sovrascritture accidentali
+ (o maliziose) che ne modifichino le istruzioni.
+
+ Viene allocato da \texttt{exec} all'avvio del programma e resta invariato
+ per tutto il tempo dell'esecuzione.
+
+\item Il segmento dei dati (\textit{data segment}). Contiene le varibili
+ globali (cioè quelle definite al di fuori di tutte le funzioni). Di norma è
+ diviso in due parti.
+
+ La prima è il segmento dei dati inizializzati, che contiene le variabili
+ globali il cui valore è stato assegnato esplicitamente. Ad esempio se si
+ definisce:
+\begin{verbatim}
+ double pi = 3.14;
+\end{verbatim}
+ questo valore sarà immagazzinato in questo segmento. La memoria di questo
+ segmento viene preallocato dalla \texttt{exec} e inizializzata ai valori
+ specificati.
+
+ La seconda è il segmento dei dati non inizializzati, che contiene le
+ variabili globali il cui valore è stato non è assegnato esplicitamente. Ad
+ esempio se si definisce:
+\begin{verbatim}
+ int vect[100];
+\end{verbatim}
+ questo valore sarà immagazzinato in questo segmento. Anch'esso viene
+ allocato all'avvio, e tutte le varibili vengono inizializzate a
+ zero (ed i puntatori a \texttt{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
+
+ \caption{Disposizione tipica dei segmenti di memoria di un processo}
+ \label{fig:proc_mem_layout}
+\end{figure}