+Come accennato le funzioni usate per effettuare un'uscita ``\textit{normale}''
+da un programma sono due, la prima è la funzione \funcd{exit}, che è definita
+dallo standard ANSI C ed il cui prototipo è:
+\begin{prototype}{stdlib.h}{void exit(int status)}
+ Causa la conclusione ordinaria del programma.
+
+ \bodydesc{La funzione non ritorna. Il processo viene terminato.}
+\end{prototype}
+
+La funzione \func{exit} è pensata per eseguire una conclusione pulita di un
+programma che usi le librerie standard del C; essa esegue tutte le funzioni
+che sono state registrate con \func{atexit} e \func{on\_exit} (vedi
+sez.~\ref{sec:proc_atexit}), e chiude tutti gli stream effettuando il
+salvataggio dei dati sospesi (chiamando \func{fclose}, vedi
+sez.~\ref{sec:file_fopen}), infine passa il controllo al kernel chiamando
+\func{\_exit} e restituendo il valore di \param{status} come stato di uscita.
+
+La system call \funcd{\_exit} restituisce direttamente il controllo al kernel,
+concludendo immediatamente il processo; i dati sospesi nei buffer degli stream
+non vengono salvati e le eventuali funzioni registrate con \func{atexit} e
+\func{on\_exit} non vengono eseguite. Il prototipo della funzione è:
+\begin{prototype}{unistd.h}{void \_exit(int status)}
+ Causa la conclusione immediata del programma.
+
+ \bodydesc{La funzione non ritorna. Il processo viene terminato.}
+\end{prototype}
+
+La funzione chiude tutti i file descriptor appartenenti al processo; si tenga
+presente che questo non comporta il salvataggio dei dati bufferizzati degli
+stream, (torneremo sulle due interfacce dei file a partire da
+cap.~\ref{cha:file_intro}), fa sì che ogni figlio del processo sia adottato da
+\cmd{init} (vedi cap.~\ref{cha:process_handling}), manda un segnale
+\const{SIGCHLD} al processo padre (vedi sez.~\ref{sec:sig_job_control}) ed
+infine ritorna lo stato di uscita specificato in \param{status} che può essere
+raccolto usando la funzione \func{wait} (vedi sez.~\ref{sec:proc_wait}).
+
+
+\subsection{Le funzioni \func{atexit} e \func{on\_exit}}
+\label{sec:proc_atexit}
+
+Un'esigenza comune che si incontra nella programmazione è quella di dover
+effettuare una serie di operazioni di pulizia (ad esempio salvare dei dati,
+ripristinare delle impostazioni, eliminare dei file temporanei, ecc.) prima
+della conclusione di un programma. In genere queste operazioni vengono fatte
+in un'apposita sezione del programma, ma quando si realizza una libreria
+diventa antipatico dover richiedere una chiamata esplicita ad una funzione di
+pulizia al programmatore che la utilizza.
+
+È invece molto meno soggetto ad errori, e completamente trasparente
+all'utente, avere la possibilità di effettuare automaticamente la chiamata ad
+una funzione che effettui tali operazioni all'uscita dal programma. A questo
+scopo lo standard ANSI C prevede la possibilità di registrare un certo numero
+di funzioni che verranno eseguite all'uscita dal programma (sia per la
+chiamata ad \func{exit} che per il ritorno di \func{main}). La prima funzione
+che si può utilizzare a tal fine è \funcd{atexit} il cui prototipo è:
+\begin{prototype}{stdlib.h}{void atexit(void (*function)(void))}
+ Registra la funzione \param{function} per la chiamata all'uscita dal
+ programma.
+
+ \bodydesc{La funzione restituisce $0$ in caso di successo e $-1$ in caso di
+ fallimento, \var{errno} non viene modificata.}
+\end{prototype}
+\noindent la funzione richiede come argomento l'indirizzo di una opportuna
+funzione di pulizia da chiamare all'uscita del programma, che non deve
+prendere argomenti e non deve ritornare niente (deve essere cioè definita come
+\code{void function(void)}).
+
+Un'estensione di \func{atexit} è la funzione \funcd{on\_exit}, che le
+\acr{glibc} includono per compatibilità con SunOS, ma che non è detto sia
+definita su altri sistemi; il suo prototipo è:
+\begin{prototype}{stdlib.h}
+{void on\_exit(void (*function)(int , void *), void *arg)}
+ Registra la funzione \param{function} per la chiamata all'uscita dal
+ programma.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ fallimento, \var{errno} non viene modificata.}
+\end{prototype}
+
+In questo caso la funzione da chiamare all'uscita prende i due argomenti
+specificati nel prototipo, dovrà cioè essere definita come \code{void
+ function(int status, void *argp)}. Il primo argomento sarà inizializzato
+allo stato di uscita con cui è stata chiamata \func{exit} ed il secondo al
+puntatore \param{arg} passato come secondo argomento di \func{on\_exit}. Così
+diventa possibile passare dei dati alla funzione di chiusura.
+
+Nella sequenza di chiusura tutte le funzioni registrate verranno chiamate in
+ordine inverso rispetto a quello di registrazione (ed una stessa funzione
+registrata più volte sarà chiamata più volte); poi verranno chiusi tutti gli
+stream aperti, infine verrà chiamata \func{\_exit}.
+
+
+\subsection{Conclusioni}
+\label{sec:proc_term_conclusion}
+
+Data l'importanza dell'argomento è opportuno sottolineare ancora una volta che
+in un sistema Unix l'unico modo in cui un programma può essere eseguito dal
+kernel è attraverso la chiamata alla system call \func{execve} (o attraverso
+una delle funzioni della famiglia \func{exec} che vedremo in
+sez.~\ref{sec:proc_exec}).
+
+Allo stesso modo l'unico modo in cui un programma può concludere
+volontariamente la sua esecuzione è attraverso una chiamata alla system call
+\func{\_exit}, o esplicitamente, o in maniera indiretta attraverso l'uso di
+\func{exit} o il ritorno di \func{main}.
+
+Uno schema riassuntivo che illustra le modalità con cui si avvia e conclude
+normalmente un programma è riportato in fig.~\ref{fig:proc_prog_start_stop}.
+
+\begin{figure}[htb]
+ \centering
+% \includegraphics[width=9cm]{img/proc_beginend}
+ \begin{tikzpicture}[>=stealth]
+ \filldraw[fill=black!35] (-0.3,0) rectangle (12,1);
+ \draw(5.5,0.5) node {\large{kernel}};
+
+ \filldraw[fill=black!15] (1.5,2) rectangle (4,3);
+ \draw (2.75,2.5) node {\texttt{ld-linux.so}};
+ \draw [->] (2.75,1) -- (2.75,2);
+ \draw (2.75,1.5) node [anchor=west]{\texttt{exec}};
+
+ \filldraw[fill=black!15,rounded corners] (1.5,4) rectangle (4,5);
+ \draw (2.75,4.5) node {\texttt{main}};
+
+ \draw [<->, dashed] (2.75,3) -- (2.75,4);
+ \draw [->] (1.5,4.5) -- (0.3,4.5) -- (0.3,1);
+ \draw (0.9,4.5) node [anchor=south] {\texttt{\_exit}};
+
+ \filldraw[fill=black!15,rounded corners] (1.5,6) rectangle (4,7);
+ \draw (2.75,6.5) node {\texttt{funzione}};
+
+ \draw [<->, dashed] (2.75,5) -- (2.75,6);
+ \draw [->] (1.5,6.5) -- (0.05,6.5) -- (0.05,1);
+ \draw (0.9,6.5) node [anchor=south] {\texttt{\_exit}};
+
+ \draw (6.75,4.5) node (exit) [rectangle,fill=black!15,minimum width=2.5cm,minimum height=1cm,rounded corners, draw]{\texttt{exit}};
+
+ \draw[->] (4,6.5) -- node[anchor=south west]{\texttt{exit}} (exit);
+ \draw[->] (4,4.5) -- node[anchor=south]{\texttt{exit}} (exit);
+ \draw[->] (exit) -- node[anchor=east]{\texttt{\_exit}}(6.75,1);
+
+ \draw (10,4.5) node (exithandler1) [rectangle,fill=black!15,rounded corners, draw]{exit handler};
+ \draw (10,5.5) node (exithandler2) [rectangle,fill=black!15,rounded corners, draw]{exit handler};
+ \draw (10,3.5) node (stream) [rectangle,fill=black!15,rounded corners, draw]{chiusura stream};
+
+ \draw[<->, dashed] (exithandler1) -- (exit);
+ \draw[<->, dashed] (exithandler2) -- (exit);
+ \draw[<->, dashed] (stream) -- (exit);
+ \end{tikzpicture}
+ \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}); tratteremo nei dettagli i segnali e la
+loro gestione nel capitolo \ref{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, e
+la gestione della memoria è appunto uno degli aspetti più complessi di un
+sistema unix-like. In questa sezione, dopo una breve introduzione ai concetti
+base, esamineremo come la memoria viene vista da parte di un programma in
+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 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 \index{memoria~virtuale} \textsl{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
+computer; in genere detto spazio non è neppure continuo (cioè non tutti gli
+indirizzi possibili sono utilizzabili, e quelli usabili non sono
+necessariamente adiacenti).
+
+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 ciascun
+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 \index{paginazione} \textsl{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 \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
+disponibili in memoria. L'unica differenza avvertibile è quella dei tempi di
+esecuzione, che passano dai pochi nanosecondi necessari per l'accesso in RAM,
+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 della \index{paginazione} paginazione e
+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}
+\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 quella che viene
+chiamata una \itindex{segment~violation} \textit{segment violation}. 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
+\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 \index{memoria~virtuale}
+\textsl{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 \index{segmento!testo} segmento di testo o \textit{text segment}.
+ Contiene il codice del programma, delle funzioni di librerie da esso
+ utilizzate, e le costanti. Normalmente viene condiviso fra tutti i processi
+ che eseguono lo stesso programma (e anche da processi che eseguono altri
+ programmi nel caso delle librerie). 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 \index{segmento!dati} segmento dei dati o \textit{data segment}.
+ Contiene le variabili globali (cioè quelle definite al di fuori di tutte le
+ funzioni che compongono il programma) e le variabili statiche (cioè quelle
+ dichiarate con l'attributo \ctyp{static}). Di norma è diviso in due parti.
+
+ La prima parte è il segmento dei dati inizializzati, che contiene le
+ variabili il cui valore è stato assegnato esplicitamente. Ad esempio
+ se si definisce:
+\includecodesnip{listati/pi.c}
+ questo valore sarà immagazzinato in questo segmento. La memoria di questo
+ segmento viene preallocata all'avvio del programma e inizializzata ai valori
+ specificati.
+
+ La seconda parte è il segmento dei dati non inizializzati, che contiene le
+ variabili il cui valore non è stato assegnato esplicitamente. Ad esempio se
+ si definisce:
+\includecodesnip{listati/vect.c}
+ questo vettore sarà immagazzinato in questo segmento. Anch'esso viene
+ allocato all'avvio, e tutte le variabili vengono inizializzate a zero (ed i
+ puntatori a \val{NULL}).\footnote{si ricordi che questo vale solo per le
+ variabili che vanno nel segmento dati, e non è affatto vero in generale.}
+
+ Storicamente questa seconda parte del segmento dati viene chiamata BSS (da
+ \textit{Block Started by Symbol}). La sua dimensione è fissa.
+
+\item Lo \itindex{heap} \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 sez.~\ref{sec:proc_mem_alloc}), ma il suo limite inferiore
+ (quello adiacente al segmento dati) ha una posizione fissa.
+
+\item Il segmento di \itindex{stack} \textit{stack}, che contiene quello che
+ viene chiamato \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. Tutti questi dati vengono \textit{impilati} (da questo
+ viene il nome \itindex{stack} \textit{stack}) in sequenza uno sull'altro; in
+ questo modo le funzioni possono essere chiamate ricorsivamente. Al ritorno
+ della funzione lo spazio è automaticamente rilasciato e
+ ``\textsl{ripulito}''.\footnote{il compilatore si incarica di generare
+ automaticamente il codice necessario, seguendo quella che viene chiamata
+ una \textit{calling convention}; quella standard usata con il C ed il C++
+ è detta \textit{cdecl} e prevede che gli argomenti siano caricati nello
+ \textit{stack} dal chiamante da destra a sinistra, e che si il chiamante
+ stesso ad eseguire la ripulitura dello \textit{stack} al ritorno della
+ funzione, se ne possono però utilizzare di alternative (ad esempio nel
+ pascal gli argomenti sono inseriti da sinistra a destra ed è compito del
+ chiamato ripulire lo \textit{stack}), in genere non ci si deve preoccupare
+ di questo fintanto che non si mescolano funzioni scritte con linguaggi
+ diversi.}
+
+ La dimensione di questo segmento aumenta seguendo la crescita dello
+ \itindex{stack} \textit{stack} del programma, ma non viene ridotta quando
+ quest'ultimo si restringe.
+\end{enumerate}
+
+\begin{figure}[htb]
+ \centering
+% \includegraphics[height=12cm]{img/memory_layout}
+ \begin{tikzpicture}
+ \draw (0,0) rectangle (4,1);
+ \draw (2,0.5) node {text};
+ \draw (0,1) rectangle (4,2.5);
+ \draw (2,1.75) node {dati inizializzati};
+ \draw (0,2.5) rectangle (4,5);
+ \draw (2,3.75) node {dati non inizializzati};
+ \draw (0,5) rectangle (4,9);
+ \draw[dashed] (0,6) -- (4,6);
+ \draw[dashed] (0,8) -- (4,8);
+ \draw (2,5.5) node {heap};
+ \draw (2,8.5) node {stack};
+ \draw [->] (2,6) -- (2,6.5);
+ \draw [->] (2,8) -- (2,7.5);
+ \draw (0,9) rectangle (4,10);
+ \draw (2,9.5) node {environment};
+ \draw (4,0) node [anchor=west] {\texttt{0x08000000}};
+ \draw (4,5) node [anchor=west] {\texttt{0x08xxxxxx}};
+ \draw (4,9) node [anchor=west] {\texttt{0xC0000000}};
+ \end{tikzpicture}
+ \caption{Disposizione tipica dei segmenti di memoria di un processo.}
+ \label{fig:proc_mem_layout}
+\end{figure}
+
+Una disposizione tipica dei vari segmenti (testo, \itindex{heap}
+\textit{heap}, \itindex{stack} \textit{stack}, ecc.) è riportata in
+fig.~\ref{fig:proc_mem_layout}. Usando il comando \cmd{size} su un programma
+se ne può stampare le dimensioni dei segmenti di testo e di dati
+(inizializzati e BSS); si tenga presente però che il BSS non è mai salvato sul
+file che contiene l'eseguibile, dato che viene sempre inizializzato a zero al
+caricamento del programma.
+
+
+\subsection{Allocazione della memoria per i programmi C}
+\label{sec:proc_mem_alloc}
+
+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
+mantenuto per tutta la durata del programma. Come accennato queste variabili
+vengono allocate nel \index{segmento!dati} segmento dei dati all'avvio del
+programma (come parte delle operazioni svolte da \func{exec}) e lo spazio da
+loro occupato non viene liberato fino alla sua conclusione.
+
+L'\textsl{allocazione automatica} è quella che avviene per gli argomenti di
+una funzione e per le sue variabili locali (le cosiddette \textsl{variabili
+ automatiche}), che esistono solo per la durata della funzione. Lo spazio
+per queste variabili viene allocato nello \itindex{stack} \textit{stack} quando
+viene eseguita la funzione e liberato quando si esce dalla medesima.
+
+Esiste però un terzo tipo di allocazione, l'\textsl{allocazione dinamica}
+della memoria, che non è prevista direttamente all'interno del linguaggio C,
+ma che è necessaria quando il quantitativo di memoria che serve è
+determinabile solo durante il corso dell'esecuzione del programma.
+
+Il C non consente di usare variabili allocate dinamicamente, non è possibile
+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 \itindex{heap}
+\textit{heap}).
+
+Le variabili il cui contenuto è allocato in questo modo non potranno essere
+usate direttamente come le altre (quelle nello \itindex{stack}
+\textit{stack}), ma l'accesso sarà possibile solo in maniera indiretta,
+attraverso i puntatori alla memoria loro riservata che si sono ottenuti dalle
+funzioni di allocazione.
+
+
+Le funzioni previste dallo standard ANSI C per la gestione della memoria sono
+quattro: \funcd{malloc}, \funcd{calloc}, \funcd{realloc} e \funcd{free}, i
+loro prototipi sono i seguenti:
+\begin{functions}
+\headdecl{stdlib.h}
+\funcdecl{void *calloc(size\_t nmemb, size\_t size)}
+ Alloca nello \textit{heap} un'area di memoria per un vettore di
+ \param{nmemb} membri di \param{size} byte di dimensione. La memoria viene
+ inizializzata a 0.
+
+ La funzione restituisce il puntatore alla zona di memoria allocata in caso
+ di successo e \val{NULL} in caso di fallimento, nel qual caso
+ \var{errno} assumerà il valore \errval{ENOMEM}.
+\funcdecl{void *malloc(size\_t size)}
+ Alloca \param{size} byte nello \textit{heap}. La memoria non viene
+ inizializzata.
+
+ La funzione restituisce il puntatore alla zona di memoria allocata in caso
+ di successo e \val{NULL} in caso di fallimento, nel qual caso
+ \var{errno} assumerà il valore \errval{ENOMEM}.
+\funcdecl{void *realloc(void *ptr, size\_t size)}
+ Cambia la dimensione del blocco allocato all'indirizzo \param{ptr}
+ portandola a \param{size}.
+
+ La funzione restituisce il puntatore alla zona di memoria allocata in caso
+ di successo e \val{NULL} in caso di fallimento, nel qual caso
+ \var{errno} assumerà il valore \errval{ENOMEM}.
+\funcdecl{void free(void *ptr)}
+ Disalloca lo spazio di memoria puntato da \param{ptr}.
+
+ La funzione non ritorna nulla e non riporta errori.
+\end{functions}
+Il puntatore ritornato dalle funzioni di allocazione è garantito essere sempre
+allineato correttamente per tutti i tipi di dati; ad esempio sulle macchine a
+32 bit in genere è allineato a multipli di 4 byte e sulle macchine a 64 bit a
+multipli di 8 byte.
+
+In genere si usano le funzioni \func{malloc} e \func{calloc} per allocare
+dinamicamente la quantità di memoria necessaria al programma indicata da
+\param{size},\footnote{queste funzioni presentano un comportamento diverso fra
+ le \acr{glibc} e le \acr{uClib} quando il valore di \param{size} è nullo.
+ Nel primo caso viene comunque restituito un puntatore valido, anche se non è
+ chiaro a cosa esso possa fare riferimento, nel secondo caso viene restituito
+ \val{NULL}. Il comportamento è analogo con \code{realloc(NULL, 0)}.} e
+siccome i puntatori ritornati sono di tipo generico non è necessario
+effettuare un cast per assegnarli a puntatori al tipo di variabile per la
+quale si effettua l'allocazione.
+
+La memoria allocata dinamicamente deve essere esplicitamente rilasciata usando
+\func{free}\footnote{le glibc provvedono anche una funzione \func{cfree}
+ definita per compatibilità con SunOS, che è deprecata.} una volta che non
+sia più necessaria. Questa funzione vuole come argomento un puntatore
+restituito da una precedente chiamata a una qualunque delle funzioni di
+allocazione che non sia già stato liberato da un'altra chiamata a \func{free},
+in caso contrario il comportamento della funzione è indefinito.
+
+La funzione \func{realloc} si usa invece per cambiare (in genere aumentare) la
+dimensione di un'area di memoria precedentemente allocata, la funzione vuole
+in ingresso il puntatore restituito dalla precedente chiamata ad una
+\func{malloc} (se è passato un valore \val{NULL} allora la funzione si
+comporta come \func{malloc})\footnote{questo è vero per Linux e
+ l'implementazione secondo lo standard ANSI C, ma non è vero per alcune
+ vecchie implementazioni, inoltre alcune versioni delle librerie del C
+ consentivano di usare \func{realloc} anche per un puntatore liberato con
+ \func{free} purché non ci fossero state nel frattempo altre chiamate a
+ funzioni di allocazione, questa funzionalità è totalmente deprecata e non è
+ consentita sotto Linux.} ad esempio quando si deve far crescere la
+dimensione di un vettore. In questo caso se è disponibile dello spazio
+adiacente al precedente la funzione lo utilizza, altrimenti rialloca altrove
+un blocco della dimensione voluta, copiandoci automaticamente il contenuto; lo
+spazio aggiunto non viene inizializzato.
+
+Si deve sempre avere ben presente il fatto che il blocco di memoria restituito
+da \func{realloc} può non essere un'estensione di quello che gli si è passato
+in ingresso; per questo si dovrà \emph{sempre} eseguire la riassegnazione di
+\param{ptr} al valore di ritorno della funzione, e reinizializzare o provvedere
+ad un adeguato aggiornamento di tutti gli altri puntatori all'interno del
+blocco di dati ridimensionato.
+
+Un errore abbastanza frequente (specie se si ha a che fare con vettori di
+puntatori) è quello di chiamare \func{free} più di una volta sullo stesso
+puntatore; per evitare questo problema una soluzione di ripiego è quella di
+assegnare sempre a \val{NULL} ogni puntatore liberato con \func{free}, dato
+che, quando l'argomento è un puntatore nullo, \func{free} non esegue nessuna
+operazione.
+
+Le \acr{glibc} hanno un'implementazione delle funzioni di allocazione che è
+controllabile dall'utente attraverso alcune variabili di ambiente (vedi
+sez.~\ref{sec:proc_environ}), in particolare diventa possibile tracciare
+questo tipo di errori usando la variabile di ambiente \val{MALLOC\_CHECK\_}
+che quando viene definita mette in uso una versione meno efficiente delle
+funzioni suddette, che però è più tollerante nei confronti di piccoli errori
+come quello di chiamate doppie a \func{free}. In particolare:
+\begin{itemize}
+\item se la variabile è posta a zero gli errori vengono ignorati;
+\item se è posta ad 1 viene stampato un avviso sullo \textit{standard error}
+ (vedi sez.~\ref{sec:file_std_stream});
+\item se è posta a 2 viene chiamata \func{abort}, che in genere causa
+ l'immediata conclusione del programma.
+\end{itemize}
+
+Il problema più comune e più difficile da risolvere che si incontra con le
+funzioni di allocazione è quando non viene opportunamente liberata la memoria
+non più utilizzata, quello che in inglese viene chiamato \itindex{memory~leak}
+\textit{memory leak}, cioè una \textsl{perdita di memoria}.
+
+Un caso tipico che illustra il problema è quello in cui in una subroutine si
+alloca della memoria per uso locale senza liberarla prima di uscire. La
+memoria resta così allocata fino alla terminazione del processo. Chiamate
+ripetute alla stessa subroutine continueranno ad effettuare altre allocazioni,
+causando a lungo andare un esaurimento della memoria disponibile (e la
+probabile impossibilità di proseguire l'esecuzione del programma).
+
+Il problema è che l'esaurimento della memoria può avvenire in qualunque
+momento, in corrispondenza ad una qualunque chiamata di \func{malloc} che può
+essere in una sezione del codice che non ha alcuna relazione con la subroutine
+che contiene l'errore. Per questo motivo è sempre molto difficile trovare un
+\itindex{memory~leak} \textit{memory leak}.
+
+In C e C++ il problema è particolarmente sentito. In C++, per mezzo della
+programmazione ad oggetti, il problema dei \itindex{memory~leak}
+\textit{memory leak} è notevolmente ridimensionato attraverso l'uso accurato
+di appositi oggetti come gli \textit{smartpointers}. Questo però in genere va
+a scapito delle prestazioni dell'applicazione in esecuzione.
+
+% TODO decidere cosa fare di questo che segue
+% In altri linguaggi come il java e recentemente il C\# il problema non si pone
+% nemmeno perché la gestione della memoria viene fatta totalmente in maniera
+% automatica, ovvero il programmatore non deve minimamente preoccuparsi di
+% liberare la memoria allocata precedentemente quando non serve più, poiché
+% l'infrastruttura del linguaggio gestisce automaticamente la cosiddetta
+% \index{\textit{garbage~collection}} \textit{garbage collection}. In tal caso,
+% attraverso meccanismi simili a quelli del \textit{reference counting}, quando
+% una zona di memoria precedentemente allocata non è più riferita da nessuna
+% parte del codice in esecuzione, può essere deallocata automaticamente in
+% qualunque momento dall'infrastruttura.
+
+% Anche questo va a scapito delle prestazioni dell'applicazione in esecuzione
+% (inoltre le applicazioni sviluppate con tali linguaggi di solito non sono
+% eseguibili compilati, come avviene invece per il C ed il C++, ed è necessaria
+% la presenza di una infrastruttura per la loro interpretazione e pertanto hanno
+% di per sé delle prestazioni più scadenti rispetto alle stesse applicazioni
+% compilate direttamente). Questo comporta però il problema della non
+% predicibilità del momento in cui viene deallocata la memoria precedentemente
+% allocata da un oggetto.
+
+Per limitare l'impatto di questi problemi, e semplificare la ricerca di
+eventuali errori, l'implementazione delle funzioni di allocazione delle
+\acr{glibc} mette a disposizione una serie di funzionalità che permettono di
+tracciare le allocazioni e le disallocazioni, e definisce anche una serie di
+possibili \textit{hook} (\textsl{ganci}) che permettono di sostituire alle
+funzioni di libreria una propria versione (che può essere più o meno
+specializzata per il debugging). Esistono varie librerie che forniscono dei
+sostituti opportuni delle funzioni di allocazione in grado, senza neanche
+ricompilare il programma,\footnote{esempi sono \textit{Dmalloc}
+ \href{http://dmalloc.com/}{\textsf{http://dmalloc.com/}} di Gray Watson ed
+ \textit{Electric Fence} di Bruce Perens.} di eseguire diagnostiche anche
+molto complesse riguardo l'allocazione della memoria. Vedremo alcune delle
+funzionalità di ausilio presenti nelle \acr{glibc} in
+sez.~\ref{sec:proc_memory_adv_management}.
+
+Una possibile alternativa all'uso di \func{malloc}, per evitare di soffrire
+dei problemi di \itindex{memory~leak} \textit{memory leak} descritti in
+precedenza, è di allocare la memoria nel segmento di \itindex{stack}
+\textit{stack} della funzione corrente invece che nello \itindex{heap}
+\textit{heap}, per farlo si può usare la funzione \funcd{alloca}, la cui
+sintassi è identica a quella di \func{malloc}; il suo prototipo è:
+\begin{prototype}{stdlib.h}{void *alloca(size\_t size)}
+ Alloca \param{size} byte nello \textit{stack}.
+
+ \bodydesc{La funzione restituisce il puntatore alla zona di memoria
+ allocata.}
+\end{prototype}
+
+La funzione alloca la quantità di memoria (non inizializzata) richiesta
+dall'argomento \param{size} nel segmento di \itindex{stack} \textit{stack}
+della funzione chiamante. Con questa funzione non è più necessario liberare
+la memoria allocata (e quindi non esiste un analogo della \func{free}) in
+quanto essa viene rilasciata automaticamente al ritorno della funzione.
+
+Come è evidente questa funzione ha molti vantaggi, anzitutto permette di
+evitare alla radice i problemi di \itindex{memory~leak} \textit{memory leak},
+dato che non serve più la deallocazione esplicita; inoltre la deallocazione
+automatica funziona anche quando si usa \func{longjmp} per uscire da una
+subroutine con un salto non locale da una funzione (vedi
+sez.~\ref{sec:proc_longjmp}).
+
+Un altro vantaggio è che in Linux la funzione è molto più veloce di
+\func{malloc} e non viene sprecato spazio, infatti non è necessario gestire un
+pool di memoria da riservare e si evitano così anche i problemi di
+frammentazione di quest'ultimo, che comportano inefficienze sia
+nell'allocazione della memoria che nell'esecuzione dell'allocazione.
+
+Gli svantaggi sono che questa funzione non è disponibile su tutti gli Unix, e
+non è inserita né nello standard POSIX né in SUSv3 (ma è presente in BSD), il
+suo utilizzo quindi limita la portabilità dei programmi. Inoltre la funzione
+non può essere usata nella lista degli argomenti di una funzione, perché lo
+spazio verrebbe allocato nel mezzo degli stessi.
+
+Inoltre non è chiaramente possibile usare \func{alloca} per allocare memoria
+che deve poi essere usata anche al di fuori della funzione in cui essa viene
+chiamata, dato che all'uscita dalla funzione lo spazio allocato diventerebbe
+libero, e potrebbe essere sovrascritto all'invocazione di nuove funzioni.
+Questo è lo stesso problema che si può avere con le variabili automatiche, su
+cui torneremo in sez.~\ref{sec:proc_auto_var}.
+
+Infine non esiste un modo di sapere se l'allocazione ha avuto successo, la
+funzione infatti viene realizzata inserendo del codice \textit{inline} nel
+programma\footnote{questo comporta anche il fatto che non è possibile
+ sostituirla con una propria versione o modificarne il comportamento
+ collegando il proprio programma con un'altra libreria.} che si limita a
+modificare il puntatore nello \itindex{stack} \textit{stack} e non c'è modo di
+sapere se se ne sono superate le dimensioni, per cui in caso di fallimento
+nell'allocazione il comportamento del programma può risultare indefinito,
+dando luogo ad una \itindex{segment~violation} \textit{segment violation} la
+prima volta che cercherà di accedere alla memoria non effettivamente
+disponibile.
+
+Le due funzioni seguenti\footnote{le due funzioni sono state definite con BSD
+ 4.3, sono marcate obsolete in SUSv2 e non fanno parte delle librerie
+ standard del C e mentre sono state esplicitamente rimosse dallo standard
+ POSIX/1-2001.} vengono utilizzate soltanto quando è necessario effettuare
+direttamente la gestione della memoria associata allo spazio dati di un
+processo, ad esempio qualora si debba implementare la propria versione delle
+funzioni di allocazione della memoria. Per poterle utilizzare è necessario
+definire una della macro di funzionalità (vedi
+sez.~\ref{sec:intro_gcc_glibc_std}) fra \macro{\_BSD\_SOURCE},
+\macro{\_SVID\_SOURCE} e \macro{\_XOPEN\_SOURCE} (ad un valore maggiore o
+ugiale di 500). La prima funzione è \funcd{brk}, ed il suo prototipo è:
+\begin{prototype}{unistd.h}{int brk(void *end\_data\_segment)}
+ Sposta la fine del segmento dei dati.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
+ fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}.}
+\end{prototype}
+
+La funzione è un'interfaccia all'omonima system call ed imposta l'indirizzo
+finale del \index{segmento!dati} segmento dati di un processo all'indirizzo
+specificato da \param{end\_data\_segment}. Quest'ultimo deve essere un valore
+ragionevole, ed inoltre la dimensione totale del segmento non deve comunque
+eccedere un eventuale limite (si veda sez.~\ref{sec:sys_resource_limit})
+imposto sulle dimensioni massime dello spazio dati del processo.
+
+Il valore di ritorno della funzione fa riferimento alla versione fornita dalle
+\acr{glibc}, in realtà in Linux la \textit{system call} corrispondente
+restituisce come valore di ritorno il nuovo valore della fine del
+\index{segmento!dati} segmento dati in caso di successo e quello corrente in
+caso di fallimento, è la funzione di interfaccia usata dalle \acr{glibc} che
+fornisce i valori di ritorno appena descritti, questo può non accadere se si
+usano librerie diverse.
+
+Una seconda funzione per la manipolazione diretta delle dimensioni
+\index{segmento!dati} del segmento dati\footnote{in questo caso si tratta
+ soltanto di una funzione di libreria, e non di una system call.} è
+\funcd{sbrk}, ed il suo prototipo è:
+\begin{prototype}{unistd.h}{void *sbrk(ptrdiff\_t increment)}
+ Incrementa la dimensione dello spazio dati.
+
+ \bodydesc{La funzione restituisce il puntatore all'inizio della nuova zona
+ di memoria allocata in caso di successo e \val{NULL} in caso di
+ fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}.}
+\end{prototype}
+\noindent la funzione incrementa la dimensione lo spazio dati di un programma
+di \param{increment} byte, restituendo il nuovo indirizzo finale dello stesso.
+Un valore nullo permette di ottenere l'attuale posizione della fine del
+\index{segmento!dati} segmento dati.
+
+Queste funzioni sono state deliberatamente escluse dallo standard POSIX.1 e
+per i programmi normali è sempre opportuno usare le funzioni di allocazione
+standard descritte in precedenza, che sono costruite su di esse.
+
+
+\subsection{Il controllo della memoria virtuale}
+\label{sec:proc_mem_lock}
+
+\index{memoria~virtuale|(}
+
+Come spiegato in sez.~\ref{sec:proc_mem_gen} il kernel gestisce la memoria
+virtuale in maniera trasparente ai processi, decidendo quando rimuovere pagine
+dalla memoria per metterle nello swap, sulla base dell'utilizzo corrente da
+parte dei vari processi.
+
+Nell'uso comune un processo non deve preoccuparsi di tutto ciò, in quanto il
+meccanismo della \index{paginazione} paginazione riporta in RAM, ed in maniera
+trasparente, tutte le pagine che gli occorrono; esistono però esigenze
+particolari in cui non si vuole che questo meccanismo si attivi. In generale i
+motivi per cui si possono avere di queste necessità sono due:
+\begin{itemize}
+\item \textsl{La velocità}. Il processo della \index{paginazione} paginazione
+ è trasparente solo se il programma in esecuzione non è sensibile al tempo
+ che occorre a riportare la pagina in memoria; per questo motivo processi
+ critici che hanno esigenze di tempo reale o tolleranze critiche nelle
+ risposte (ad esempio processi che trattano campionamenti sonori) possono non
+ essere in grado di sopportare le variazioni della velocità di accesso dovuta
+ alla paginazione.
+
+ In certi casi poi un programmatore può conoscere meglio dell'algoritmo di
+ allocazione delle pagine le esigenze specifiche del suo programma e decidere
+ quali pagine di memoria è opportuno che restino in memoria per un aumento
+ delle prestazioni. In genere queste sono esigenze particolari e richiedono
+ anche un aumento delle priorità in esecuzione del processo (vedi
+ sez.~\ref{sec:proc_real_time}).
+
+\item \textsl{La sicurezza}. Se si hanno password o chiavi segrete in chiaro
+ in memoria queste possono essere portate su disco dal meccanismo della
+ \index{paginazione} paginazione. Questo rende più lungo il periodo di tempo
+ in cui detti segreti sono presenti in chiaro e più complessa la loro
+ cancellazione (un processo può cancellare la memoria su cui scrive le sue
+ variabili, ma non può toccare lo spazio disco su cui una pagina di memoria
+ può essere stata salvata). Per questo motivo di solito i programmi di
+ crittografia richiedono il blocco di alcune pagine di memoria.
+\end{itemize}
+
+Per ottenere informazioni sulle modalità in cui un programma sta usando la
+memoria virtuale è disponibile una apposita funzione, \funcd{mincore}, che
+però non è standardizzata da POSIX e pertanto non è disponibile su tutte le
+versioni di kernel unix-like;\footnote{nel caso di Linux devono essere
+ comunque definite le macro \macro{\_BSD\_SOURCE} e \macro{\_SVID\_SOURCE}.}
+il suo prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{sys/mman.h}
+
+ \funcdecl{int mincore(void *addr, size\_t length, unsigned char *vec)}
+ Ritorna lo stato delle pagine di memoria occupate da un processo.
+
+ \bodydesc{La funzione ritorna 0 in caso di successo e $-1$ in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori seguenti:
+ \begin{errlist}
+ \item[\errcode{ENOMEM}] o \param{addr} + \param{length} eccede la dimensione
+ della memoria usata dal processo o l'intervallo di indirizzi specificato
+ non è mappato.
+ \item[\errcode{EINVAL}] \param{addr} non è un multiplo delle dimensioni di
+ una pagina.
+ \item[\errcode{EFAULT}] \param{vec} punta ad un indirizzo non valido.
+ \item[\errcode{EAGAIN}] il kernel è temporaneamente non in grado di fornire
+ una risposta.
+ \end{errlist}
+}
+\end{functions}
+
+La funzione permette di ottenere le informazioni sullo stato della mappatura
+della memoria per il processo chiamante, specificando l'intervallo da
+esaminare con l'indirizzo iniziale (indicato con l'argomento \param{addr}) e
+la lunghezza (indicata con l'argomento \param{length}). L'indirizzo iniziale
+deve essere un multiplo delle dimensioni di una pagina, mentre la lunghezza
+può essere qualunque, fintanto che si resta nello spazio di indirizzi del
+processo,\footnote{in caso contrario si avrà un errore di \errcode{ENOMEM};
+ fino al kernel 2.6.11 in questo caso veniva invece restituito
+ \errcode{EINVAL}, in considerazione che il caso più comune in cui si
+ verifica questo errore è quando si usa per sbaglio un valore negativo
+ di \param{length}, che nel caso verrebbe interpretato come un intero
+ positivo di grandi dimensioni.} ma il risultato verrà comunque fornito per
+l'intervallo compreso fino al multiplo successivo.
+
+I risultati della funzione vengono forniti nel vettore puntato da \param{vec},
+che deve essere allocato preventivamente e deve essere di dimensione
+sufficiente a contenere tanti byte quante sono le pagine contenute
+nell'intervallo di indirizzi specificato.\footnote{la dimensione cioè deve
+ essere almeno pari a \code{(length+PAGE\_SIZE-1)/PAGE\_SIZE}. } Al ritorno
+della funzione il bit meno significativo di ciascun byte del vettore sarà
+acceso se la pagina di memoria corrispondente è al momento residente in
+memoria, o cancellato altrimenti. Il comportamento sugli altri bit è
+indefinito, essendo questi al momento riservati per usi futuri. Per questo
+motivo in genere è comunque opportuno inizializzare a zero il contenuto del
+vettore, così che le pagine attualmente residenti in memoria saranno indicata
+da un valore non nullo del byte corrispondente.
+
+Dato che lo stato della memoria di un processo può cambiare continuamente, il
+risultato di \func{mincore} è assolutamente provvisorio e lo stato delle
+pagine potrebbe essere già cambiato al ritorno stesso della funzione, a meno
+che, come vedremo ora, non si sia attivato il meccanismo che forza il
+mantenimento di una pagina sulla memoria.
+
+\itindbeg{memory~locking}
+
+Il meccanismo che previene la \index{paginazione} paginazione di parte della
+memoria virtuale di un processo è chiamato \textit{memory locking} (o
+\textsl{blocco della memoria}). Il blocco è sempre associato alle pagine della
+memoria virtuale del processo, e non al segmento reale di RAM su cui essa
+viene mantenuta. La regola è che se un segmento di RAM fa da supporto ad
+almeno una pagina bloccata allora esso viene escluso dal meccanismo della
+\index{paginazione} paginazione. I blocchi non si accumulano, se si blocca due
+volte la stessa pagina non è necessario sbloccarla due volte, una pagina o è
+bloccata oppure no.
+
+Il \textit{memory lock} persiste fintanto che il processo che detiene la
+memoria bloccata non la sblocca. Chiaramente la terminazione del processo
+comporta anche la fine dell'uso della sua memoria virtuale, e quindi anche di
+tutti i suoi \textit{memory lock}. Infine i \textit{memory lock} non sono
+ereditati dai processi figli,\footnote{ma siccome Linux usa il
+ \itindex{copy~on~write} \textit{copy on write} (vedi
+ sez.~\ref{sec:proc_fork}) gli indirizzi virtuali del figlio sono mantenuti
+ sullo stesso segmento di RAM del padre, quindi fintanto che un figlio non
+ scrive su un segmento, può usufruire del \textit{memory lock} del padre.} e
+vengono automaticamente rimossi se si pone in esecuzione un altro programma
+con \func{exec} (vedi sez.~\ref{sec:proc_exec}).
+
+Siccome la richiesta di un \textit{memory lock} da parte di un processo riduce
+la memoria fisica disponibile nel sistema, questo ha un evidente impatto su
+tutti gli altri processi, per cui fino al kernel 2.6.9 solo un processo con i
+privilegi opportuni (la \itindex{capabilities} \textit{capability}
+\const{CAP\_IPC\_LOCK}, vedi sez.~\ref{sec:proc_capabilities}) aveva la
+capacità di bloccare una pagina.
+
+Il sistema pone dei limiti all'ammontare di memoria di un processo che può
+essere bloccata e al totale di memoria fisica che si può dedicare a questo, lo
+standard POSIX.1 richiede che sia definita in \file{unistd.h} la macro
+\macro{\_POSIX\_MEMLOCK\_RANGE} per indicare la capacità di eseguire il
+\textit{memory locking}. Inoltre in alcuni sistemi è definita la costante
+\const{PAGE\_SIZE} in \file{limits.h} per indicare la dimensione di una pagina
+in byte.\footnote{con Linux questo non avviene e si deve ricorrere alla
+ funzione \func{getpagesize}, vedi sez.~\ref{sec:sys_memory_res}.}
+
+A partire dal kernel 2.6.9 anche un processo normale può bloccare la propria
+memoria\footnote{la funzionalità è stata introdotta per non essere costretti a
+ dare privilegi eccessivi a programmi di crittografia, che necessitano di
+ questa funzionalità, ma che devono essere usati da utenti normali.} ma
+mentre un processo privilegiato non ha limiti sulla quantità di memoria che
+può bloccare, un processo normale è soggetto al limite della risorsa
+\const{RLIMIT\_MEMLOCK} (vedi sez.~\ref{sec:sys_resource_limit}). In generale
+poi ogni processo può sbloccare le pagine relative alla propria memoria, se
+però diversi processi bloccano la stessa pagina questa resterà bloccata
+fintanto che ci sarà almeno un processo che la blocca.
+
+Le funzioni per bloccare e sbloccare la \index{paginazione} paginazione di
+singole sezioni di memoria sono \funcd{mlock} e \funcd{munlock}; i loro
+prototipi sono:
+\begin{functions}
+ \headdecl{sys/mman.h}
+
+ \funcdecl{int mlock(const void *addr, size\_t len)}
+ Blocca la paginazione su un intervallo di memoria.
+
+ \funcdecl{int munlock(const void *addr, size\_t len)}
+ Rimuove il blocco della paginazione su un intervallo di memoria.
+
+ \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e $-1$ in
+ caso di errore, nel qual caso \var{errno} assumerà uno dei
+ valori seguenti:
+ \begin{errlist}
+ \item[\errcode{ENOMEM}] alcuni indirizzi dell'intervallo specificato non
+ corrispondono allo spazio di indirizzi del processo o si è ecceduto
+ il numero massimo consentito di pagine bloccate.
+ \item[\errcode{EINVAL}] \param{len} non è un valore positivo.
+ \item[\errcode{EPERM}] con un kernel successivo al 2.6.9 il processo non è
+ privilegiato e si un limite nullo per \const{RLIMIT\_MEMLOCK}.
+ \end{errlist}
+ e, per \func{mlock}, anche \errval{EPERM} quando il processo non ha i
+ privilegi richiesti per l'operazione.}
+\end{functions}
+
+Le due funzioni permettono rispettivamente di bloccare e sbloccare la
+\index{paginazione} paginazione per l'intervallo di memoria specificato dagli
+argomenti, che ne indicano nell'ordine l'indirizzo iniziale e la lunghezza.
+Tutte le pagine che contengono una parte dell'intervallo bloccato sono
+mantenute in RAM per tutta la durata del blocco.\footnote{con altri kernel si
+ può ottenere un errore di \errcode{EINVAL} se \param{addr} non è un multiplo
+ della dimensione delle pagine di memoria.}
+
+Altre due funzioni, \funcd{mlockall} e \funcd{munlockall}, consentono di
+bloccare genericamente la \index{paginazione} paginazione per l'intero spazio
+di indirizzi di un processo. I prototipi di queste funzioni sono:
+\begin{functions}
+ \headdecl{sys/mman.h}
+
+ \funcdecl{int mlockall(int flags)}
+ Blocca la paginazione per lo spazio di indirizzi del processo corrente.
+
+ \funcdecl{int munlockall(void)}
+ Sblocca la paginazione per lo spazio di indirizzi del processo corrente.
+
+ \bodydesc{Codici di ritorno ed errori sono gli stessi di \func{mlock} e
+ \func{munlock}, con un kernel successivo al 2.6.9 l'uso di
+ \func{munlockall} senza la \itindex{capabilities} \textit{capability}
+\const{CAP\_IPC\_LOCK} genera un errore di \errcode{EPERM}.}
+\end{functions}
+
+L'argomento \param{flags} di \func{mlockall} permette di controllarne il
+comportamento; esso può essere specificato come l'OR aritmetico delle due
+costanti:
+\begin{basedescript}{\desclabelwidth{2.5cm}}
+\item[\const{MCL\_CURRENT}] blocca tutte le pagine correntemente mappate nello
+ spazio di indirizzi del processo.
+\item[\const{MCL\_FUTURE}] blocca tutte le pagine che verranno mappate nello
+ spazio di indirizzi del processo.
+\end{basedescript}
+
+Con \func{mlockall} si possono bloccare tutte le pagine mappate nello spazio
+di indirizzi del processo, sia che comprendano il \index{segmento!dati}
+\index{segmento!testo} segmento di testo, di dati, lo \itindex{stack}
+\textit{stack}, lo \itindex{heap} \textit{heap} e pure le funzioni di libreria
+chiamate, i file mappati in memoria, i dati del kernel mappati in user space,
+la memoria condivisa. L'uso dei flag permette di selezionare con maggior
+finezza le pagine da bloccare, ad esempio limitandosi a tutte le pagine
+allocate a partire da un certo momento.
+
+In ogni caso un processo real-time che deve entrare in una
+\index{sezione~critica} sezione critica deve provvedere a riservare memoria
+sufficiente prima dell'ingresso, per scongiurare l'occorrenza di un eventuale
+\itindex{page~fault} \textit{page fault} causato dal meccanismo di
+\itindex{copy~on~write} \textit{copy on write}. Infatti se nella
+\index{sezione~critica} sezione critica si va ad utilizzare memoria che non è
+ancora stata riportata in RAM si potrebbe avere un \itindex{page~fault}
+\textit{page fault} durante l'esecuzione della stessa, con conseguente
+rallentamento (probabilmente inaccettabile) dei tempi di esecuzione.