Anche il link
[gapil.git] / process.tex
index 3f500455336e5b8f1bfb686e4fdbfc1d1a95649a..4d5118c513d0386f6af0df3aa3e2c83870d4dd32 100644 (file)
@@ -1,6 +1,6 @@
 %% process.tex
 %%
 %% process.tex
 %%
-%% Copyright (C) 2000-2007 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-2009 Simone Piccardi.  Permission is granted to
 %% copy, distribute and/or modify this document under the terms of the GNU Free
 %% Documentation License, Version 1.1 or any later version published by the
 %% Free Software Foundation; with the Invariant Sections being "Un preambolo",
 %% copy, distribute and/or modify this document under the terms of the GNU Free
 %% Documentation License, Version 1.1 or any later version published by the
 %% Free Software Foundation; with the Invariant Sections being "Un preambolo",
@@ -35,8 +35,8 @@ ciascun processo vedr
 tutte le parti uguali siano condivise), avrà un suo spazio di indirizzi,
 variabili proprie e sarà eseguito in maniera completamente indipendente da
 tutti gli altri.\footnote{questo non è del tutto vero nel caso di un programma
 tutte le parti uguali siano condivise), avrà un suo spazio di indirizzi,
 variabili proprie e sarà eseguito in maniera completamente indipendente da
 tutti gli altri.\footnote{questo non è del tutto vero nel caso di un programma
-  \textit{multi-thread}, ma la gestione dei \textit{thread} in Linux sarà
-  trattata a parte.}
+  \textit{multi-thread}, ma la gestione dei \itindex{thread} \textit{thread}
+  in Linux sarà trattata a parte in cap.~\ref{cha:threads}.}
 
 
 \subsection{La funzione \func{main}} 
 
 
 \subsection{La funzione \func{main}} 
@@ -49,8 +49,8 @@ dinamico del codice e alla fine lo esegue. Infatti, a meno di non aver
 specificato il flag \texttt{-static} durante la compilazione, tutti i
 programmi in Linux sono incompleti e necessitano di essere \textsl{collegati}
 alle librerie condivise quando vengono avviati.  La procedura è controllata da
 specificato il flag \texttt{-static} durante la compilazione, tutti i
 programmi in Linux sono incompleti e necessitano di essere \textsl{collegati}
 alle librerie condivise quando vengono avviati.  La procedura è controllata da
-alcune variabili di ambiente e dal contenuto di \file{/etc/ld.so.conf}. I
-dettagli sono riportati nella man page di \cmd{ld.so}.
+alcune variabili di ambiente e dal contenuto di \conffile{/etc/ld.so.conf}. I
+dettagli sono riportati nella pagina di manuale di \cmd{ld.so}.
 
 Il sistema fa partire qualunque programma chiamando la funzione \func{main};
 sta al programmatore chiamare così la funzione principale del programma da cui
 
 Il sistema fa partire qualunque programma chiamando la funzione \func{main};
 sta al programmatore chiamare così la funzione principale del programma da cui
@@ -82,8 +82,8 @@ controllo direttamente alla funzione di conclusione dei processi del kernel.
 
 Oltre alla conclusione ``\textsl{normale}'' esiste anche la possibilità di una
 conclusione ``\textsl{anomala}'' del programma a causa della ricezione di un
 
 Oltre alla conclusione ``\textsl{normale}'' esiste anche la possibilità di una
 conclusione ``\textsl{anomala}'' del programma a causa della ricezione di un
-segnale (si veda cap.~\ref{cha:signals}) o della chiamata alla funzione
-\func{abort}; torneremo su questo in sez.~\ref{sec:proc_termination}.
+segnale (tratteremo i segnali in cap.~\ref{cha:signals}) o della chiamata alla
+funzione \func{abort}; torneremo su questo in sez.~\ref{sec:proc_termination}.
 
 Il valore di ritorno della funzione \func{main}, o quello usato nelle chiamate
 ad \func{exit} e \func{\_exit}, viene chiamato \textsl{stato di uscita} (o
 
 Il valore di ritorno della funzione \func{main}, o quello usato nelle chiamate
 ad \func{exit} e \func{\_exit}, viene chiamato \textsl{stato di uscita} (o
@@ -182,7 +182,7 @@ che si pu
   Registra la funzione \param{function} per la chiamata all'uscita dal
   programma.
   
   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
+  \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
     fallimento, \var{errno} non viene modificata.}
 \end{prototype}
 \noindent la funzione richiede come argomento l'indirizzo di una opportuna
@@ -198,7 +198,7 @@ definita su altri sistemi; il suo prototipo 
   Registra la funzione \param{function} per la chiamata all'uscita dal
   programma. 
   
   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
+  \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
     fallimento, \var{errno} non viene modificata.}
 \end{prototype}
 
     fallimento, \var{errno} non viene modificata.}
 \end{prototype}
 
@@ -234,7 +234,44 @@ normalmente un programma 
 
 \begin{figure}[htb]
   \centering
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=9cm]{img/proc_beginend}
+%  \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}
   \caption{Schema dell'avvio e della conclusione di un programma.}
   \label{fig:proc_prog_start_stop}
 \end{figure}
@@ -336,12 +373,12 @@ Inoltre per certe applicazioni gli algoritmi di gestione della memoria
 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
 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 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.
+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
 
 È pertanto importante capire come viene strutturata \index{memoria~virtuale}
 \textsl{la memoria virtuale} di un processo. Essa viene divisa in
@@ -402,10 +439,17 @@ seguenti segmenti:
   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
   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}''. La pulizia in C e C++ viene fatta dal
-  chiamante.\footnote{a meno che non sia stato specificato l'utilizzo di una
-    calling convention diversa da quella standard.}
-% TODO verificare le modalità di cambiamento della calling convention
+  ``\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
 
   La dimensione di questo segmento aumenta seguendo la crescita dello
   \itindex{stack} \textit{stack} del programma, ma non viene ridotta quando
@@ -414,7 +458,27 @@ seguenti segmenti:
 
 \begin{figure}[htb]
   \centering
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[height=12cm]{img/memory_layout}
+%  \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}
   \caption{Disposizione tipica dei segmenti di memoria di un processo.}
   \label{fig:proc_mem_layout}
 \end{figure}
@@ -560,13 +624,13 @@ 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:
 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*}
+\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.
 \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*}
+\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
 
 Il problema più comune e più difficile da risolvere che si incontra con le
 funzioni di allocazione è quando non viene opportunamente liberata la memoria
@@ -581,7 +645,7 @@ 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
 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ò
+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}.
 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}.
@@ -624,8 +688,9 @@ 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
 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.
-
+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}, che non soffre dei
 problemi di \itindex{memory~leak} \textit{memory leak} descritti in
 
 Una possibile alternativa all'uso di \func{malloc}, che non soffre dei
 problemi di \itindex{memory~leak} \textit{memory leak} descritti in
@@ -634,11 +699,10 @@ nello \itindex{heap} \textit{heap} usa il segmento di \itindex{stack}
 \textit{stack} della funzione corrente. La sintassi è identica a quella di
 \func{malloc}, il suo prototipo è:
 \begin{prototype}{stdlib.h}{void *alloca(size\_t size)}
 \textit{stack} della funzione corrente. La sintassi è identica a quella di
 \func{malloc}, il suo prototipo è:
 \begin{prototype}{stdlib.h}{void *alloca(size\_t size)}
-  Alloca \param{size} byte nello stack.
+  Alloca \param{size} byte nello \textit{stack}.
   
   
-  \bodydesc{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}.}
+  \bodydesc{La funzione restituisce il puntatore alla zona di memoria
+    allocata.}
 \end{prototype}
 
 La funzione alloca la quantità di memoria (non inizializzata) richiesta
 \end{prototype}
 
 La funzione alloca la quantità di memoria (non inizializzata) richiesta
@@ -666,16 +730,6 @@ suo utilizzo quindi limita la portabilit
 non può essere usata nella lista degli argomenti di una funzione, perché lo
 spazio verrebbe allocato nel mezzo degli stessi.
 
 non può essere usata nella lista degli argomenti di una funzione, perché lo
 spazio verrebbe allocato nel mezzo degli stessi.
 
-% Questo è riportato solo dal manuale delle glibc, nelle pagine di manuale non c'è 
-% traccia di tutto ciò
-%
-%Inoltre se si
-%cerca di allocare troppa memoria non si ottiene un messaggio di errore, ma un
-%segnale di \textit{segment violation} analogo a quello che si avrebbe da una
-%ricorsione infinita.
-% TODO inserire più informazioni su alloca come da man page
-
-
 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
 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
@@ -683,30 +737,52 @@ 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}.
 
 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
 
 Le due funzioni seguenti\footnote{le due funzioni sono state definite con BSD
-  4.3, non fanno parte delle librerie standard del C e mentre sono state
-  esplicitamente escluse dallo standard POSIX.} 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.
-La prima funzione è \funcd{brk}, ed il suo prototipo è:
+  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.
   
 \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
+  \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}
 
     fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}.}
 \end{prototype}
 
-La funzione è un'interfaccia diretta 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.
-
-Una seconda funzione per la manipolazione delle dimensioni
+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 è:
 \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 è:
@@ -768,6 +844,67 @@ motivi per cui si possono avere di queste necessit
   crittografia richiedono il blocco di alcune pagine di memoria.
 \end{itemize}
 
   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{lenght} 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
 \itindbeg{memory~locking} 
 
 Il meccanismo che previene la \index{paginazione} paginazione di parte della
@@ -808,7 +945,6 @@ standard POSIX.1 richiede che sia definita in \file{unistd.h} la macro
 in byte.\footnote{con Linux questo non avviene e si deve ricorrere alla
   funzione \func{getpagesize}, vedi sez.~\ref{sec:sys_memory_res}.} 
 
 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
 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
@@ -832,7 +968,7 @@ prototipi sono:
   \funcdecl{int munlock(const void *addr, size\_t len)}
   Rimuove il blocco della 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
+  \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}
     caso di errore, nel qual caso \var{errno} assumerà uno dei
     valori seguenti:
   \begin{errlist}
@@ -910,18 +1046,122 @@ ci si scrive sopra.
 
 \itindend{memory~locking}
 
 
 \itindend{memory~locking}
 
-% TODO documentare \func{madvise}
-% TODO documentare \func{mincore}
+\index{memoria~virtuale|)} 
 
 
 
 
-\index{memoria~virtuale|)} 
+\subsection{Gestione avanzata dell'allocazione della memoria} 
+\label{sec:proc_memory_adv_management}
+
+La trattazione delle funzioni di allocazione di sez.~\ref{sec:proc_mem_alloc}
+si è limitata a coprire le esigenze generiche di un programma, in cui non si
+hanno dei requisiti specifici e si lascia il controllo delle modalità di
+allocazione alle funzioni di libreria.  Tuttavia esistono una serie di casi in
+cui può essere necessario avere un controllo più dettagliato delle modalità
+con cui la memoria viene allocata; nel qual caso potranno venire in aiuto le
+funzioni trattate in questa sezione.
+
+Le prime funzioni che tratteremo sono quelle che consentono di richiedere di
+allocare un blocco di memoria ``\textsl{allineato}'' ad un multiplo una certa
+dimensione. Questo tipo di esigenza emerge usualmente quando si devono
+allocare dei buffer da utilizzare per eseguire dell'I/O diretto su dispositivi
+a blocchi. In questo caso infatti il trasferimento di dati viene eseguito per
+blocchi di dimensione fissa, ed è richiesto che l'indirizzo di partenza del
+buffer sia un multiplo intero di questa dimensione, usualmente 512 byte. In
+tal caso l'uso di \func{malloc} non è sufficiente, ed occorre utilizzare una
+funzione specifica.
+
+Tradizionalmente per rispondere a questa esigenza sono state crate due
+funzioni diverse, \funcd{memalign} e \funcd{valloc}, oggi obsolete; i
+rispettivi prototipi sono:
+\begin{functions}
+  \headdecl{malloc.h} 
 
 
+  \funcdecl{void *valloc(size\_t size)} Alloca un blocco di memoria allineato
+  alla dimensione di una pagina di memoria.
 
 
-% \subsection{Gestione avanzata dell'allocazione della memoria} 
-% \label{sec:proc_mem_malloc_custom}
-% TODO: trattare le funzionalità avanzate di \func{malloc}
+  \funcdecl{void *memalign(size\_t boundary, size\_t size)}
+  Alloca un blocco di memoria allineato ad un multiplo di \param{boundary}.
+  
+  \bodydesc{Entrambe le funzioni ritornano un puntatore al blocco di memoria
+    allocato in caso di successo e \val{NULL} in caso di errore, nel qual
+    caso \var{errno} assumerà uno dei valori seguenti:
+  \begin{errlist}
+  \item[\errcode{ENOMEM}] non c'è memoria sufficiente per l'allocazione.
+  \item[\errcode{EINVAL}] \param{boundary} non è multiplo di due.
+  \end{errlist}
+}
+\end{functions}
 
 
+Le funzioni restituiscono il puntatore al buffer di memoria allocata, che per
+\func{memalign} sarà un multiplo di \param{boundary} mentre per \func{valloc}
+un multiplo della dimensione di una pagina di memoria. Nel caso della versione
+fornita dalle \acr{glibc} la memoria allocata con queste funzioni deve essere
+liberata con \func{free}, cosa che non è detto accada con altre
+implementazioni.
+
+Nessuna delle due funzioni ha una chiara standardizzazione (nessuna delle due
+compare in POSIX.1), ed inoltre ci sono indicazioni discordi sui file che ne
+contengono la definizione;\footnote{secondo SUSv2 \func{valloc} è definita in
+  \texttt{stdlib.h}, mentre sia le \acr{glibc} che le precedenti \acr{libc4} e
+  \acr{lic5} la dichiarano in \texttt{malloc.h}, lo stesso vale per
+  \func{memalign} che in alcuni sistemi è dichiarata in \texttt{stdlib.h}.}
+per questo motivo il loro uso è sconsigliato, essendo state sostituite dalla
+nuova \funcd{posix\_memalign}, che è stata standardizzata in POSIX.1d; il suo
+prototipo è:
+\begin{prototype}{stdlib.h}{posix\_memalign(void **memptr, size\_t alignment,
+    size\_t size) } 
+  Alloca un buffer di memoria allineato ad un multiplo di \param{alignment}.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e \val{NULL} in caso
+    di fallimento, o uno dei due codici di errore \errcode{ENOMEM} o
+    \errcode{EINVAL}; \var{errno} non viene impostata.}
+\end{prototype}
 
 
+La funzione restituisce il puntatore al buffer allocato all'indirizzo indicato
+da \param{memptr}. La funzione fallisce nelle stesse condizioni delle due
+funzioni precedenti, ma a differenza di \func{memalign} restituisce un codice
+di errore \errcode{EINVAL} anche se \param{alignment} non è un multiplo della
+la dimensione di \code{sizeof(void *)}. Come per le precedenti la memoria
+allocata con \func{posix\_memalign} può essere disallocata con
+\func{free}.\footnote{che in caso questo caso è quanto richiesto dallo
+  standard.}
+
+Un secondo caso in cui risulta estremamente utile poter avere un maggior
+controllo delle modalità di allocazione della memoria è quello in cui cercano
+errori di programmazione. Esempi di questi errori sono chiamate doppie alla
+funzione \func{free} con lo stesso puntatore, o i cosiddetti
+\itindex{buffer~overrun} \textit{buffer overrun}, cioè le scritture su un buffer
+oltre le dimensioni della sua allocazione,\footnote{entrambe queste operazioni
+  causano in genere la corruzione dei dati di controllo delle funzioni di
+  allocazione, che vengono anch'essi mantenuti nello \itindex{heap}
+  \textit{heap} per tenere traccia delle zone di memoria allocata.} o i
+classici \itindex{memory~leak} \textit{memory leak}.
+
+Una prima funzionalità di ausilio nella ricerca di questi errori viene fornita
+dalla \acr{glibc} tramite l'uso della variabile di ambiente (vedi
+sez.~\ref{sec:proc_environ}) \var{MALLOC\_CHECK\_}. Quando questa viene
+definita al posto della versione ordinaria delle funzioni di allocazione
+(\func{malloc}, \func{calloc}, \func{realloc}, e \func{free}) viene usata una
+versione meno efficiente ma in grado di rilevare (e tollerare) alcuni degli
+errori più semplici, come le doppie chiamate a \func{free} o i
+\itindex{buffer~overrun} \textit{buffer overrun} di un byte.\footnote{uno
+  degli errori più comuni, causato ad esempio dalla scrittura di una stringa
+  di dimensione pari a quella del buffer, in cui ci si dimentica dello zero di
+  terminazione finale.} 
+
+In questo caso a seconda del valore assegnato a \var{MALLOC\_CHECK\_} si
+avranno diversi comportamenti: con 0 l'errore sarà ignorato, con 1 verrà
+stampato un messaggio sullo \textit{standard error} (vedi
+sez.~\ref{sec:file_std_stream}), con 2 verrà invocata la funzione \func{abort}
+(vedi sez.~\ref{sec:sig_alarm_abort}) che termina il programma, con 3 viene
+sia stampato il messaggio d'errore che abortito il programma. In genere è
+opportuno definire la variabile ad un valore diverso da zero che consente di
+rilevare un errore nel momento in cui avviene.
+
+% TODO: trattare le altre funzionalità avanzate di \func{malloc}, mallopt,
+% mtrace, muntrace, mcheck, mallinfo e gli hook
+% con le glibc 2.10 c'è pure malloc_info a sostituire mallinfo, vedi
+% http://udrepper.livejournal.com/20948.html
 
 \section{Argomenti, opzioni ed ambiente di un processo}
 \label{sec:proc_options}
 
 \section{Argomenti, opzioni ed ambiente di un processo}
 \label{sec:proc_options}
@@ -944,13 +1184,13 @@ manipolare ed utilizzare le variabili di ambiente.
 \subsection{Il formato degli argomenti}
 \label{sec:proc_par_format}
 
 \subsection{Il formato degli argomenti}
 \label{sec:proc_par_format}
 
-In genere il passaggio degli argomenti al programma viene effettuato dalla
+In genere il passaggio degli argomenti ad un programma viene effettuato dalla
 shell, che si incarica di leggere la linea di comando e di effettuarne la
 scansione (il cosiddetto \textit{parsing}) per individuare le parole che la
 compongono, ciascuna delle quali viene considerata un argomento. Di norma per
 shell, che si incarica di leggere la linea di comando e di effettuarne la
 scansione (il cosiddetto \textit{parsing}) per individuare le parole che la
 compongono, ciascuna delle quali viene considerata un argomento. Di norma per
-individuare le parole viene usato come carattere di separazione lo spazio o il
-tabulatore, ma il comportamento è modificabile attraverso l'impostazione della
-variabile di ambiente \cmd{IFS}.
+individuare le parole che andranno a costituire la lista degli argomenti viene
+usato come carattere di separazione lo spazio o il tabulatore, ma la cosa
+dipende ovviamente dalle modalità con cui si effettua il lancio.
 
 \begin{figure}[htb]
   \centering
 
 \begin{figure}[htb]
   \centering
@@ -960,11 +1200,13 @@ variabile di ambiente \cmd{IFS}.
   \label{fig:proc_argv_argc}
 \end{figure}
 
   \label{fig:proc_argv_argc}
 \end{figure}
 
-Nella scansione viene costruito il vettore di puntatori \param{argv} inserendo
-in successione il puntatore alla stringa costituente l'$n$-simo argomento; la
-variabile \param{argc} viene inizializzata al numero di argomenti trovati, in
-questo modo il primo argomento è sempre il nome del programma; un esempio di
-questo meccanismo è mostrato in fig.~\ref{fig:proc_argv_argc}.
+Indipendentemente da come viene eseguita, il risultato della scansione deve
+essere la costruzione del vettore di puntatori \param{argv} in cui si devono
+inserire in successione i puntatori alle stringhe costituenti i vari
+argomenti, e della variabile \param{argc} che deve essere inizializzata al
+numero di argomenti trovati. Nel caso della shell questo comporta che il primo
+argomento sia sempre il nome del programma; un esempio di questo meccanismo è
+mostrato in fig.~\ref{fig:proc_argv_argc}.
 
 
 \subsection{La gestione delle opzioni}
 
 
 \subsection{La gestione delle opzioni}
@@ -990,7 +1232,7 @@ Esegue il parsing degli argomenti passati da linea di comando
 riconoscendo le possibili opzioni segnalate con \param{optstring}.
 
 \bodydesc{Ritorna il carattere che segue l'opzione, \cmd{':'} se manca un
 riconoscendo le possibili opzioni segnalate con \param{optstring}.
 
 \bodydesc{Ritorna il carattere che segue l'opzione, \cmd{':'} se manca un
-  parametro all'opzione, \cmd{'?'} se l'opzione è sconosciuta, e -1 se non
+  parametro all'opzione, \cmd{'?'} se l'opzione è sconosciuta, e $-1$ se non
   esistono altre opzioni.}
 \end{prototype}
 
   esistono altre opzioni.}
 \end{prototype}
 
@@ -1007,7 +1249,7 @@ due punti \texttt{':'}; nel caso di fig.~\ref{fig:proc_argv_argc} ad esempio la
 stringa di opzioni avrebbe dovuto contenere \texttt{"r:m"}.
 
 La modalità di uso di \func{getopt} è pertanto quella di chiamare più volte la
 stringa di opzioni avrebbe dovuto contenere \texttt{"r:m"}.
 
 La modalità di uso di \func{getopt} è pertanto quella di chiamare più volte la
-funzione all'interno di un ciclo, fintanto che essa non ritorna il valore -1
+funzione all'interno di un ciclo, fintanto che essa non ritorna il valore $-1$
 che indica che non ci sono più opzioni. Nel caso si incontri un'opzione non
 dichiarata in \param{optstring} viene ritornato il carattere \texttt{'?'}
 mentre se un'opzione che lo richiede non è seguita da un parametro viene
 che indica che non ci sono più opzioni. Nel caso si incontri un'opzione non
 dichiarata in \param{optstring} viene ritornato il carattere \texttt{'?'}
 mentre se un'opzione che lo richiede non è seguita da un parametro viene
@@ -1068,17 +1310,6 @@ questo permette di identificare gli elementi che non sono opzioni, ma non
 effettua il riordinamento del vettore \param{argv}.
 
 
 effettua il riordinamento del vettore \param{argv}.
 
 
-\subsection{Opzioni in formato esteso}
-\label{sec:proc_opt_extended}
-
-Un'estensione di questo schema è costituita dalle cosiddette
-\textit{long-options} espresse nella forma \cmd{-{}-option=parameter}, anche
-la gestione di queste ultime è stata standardizzata attraverso l'uso di una
-versione estesa di \func{getopt}.
-
-(NdA: questa parte verrà inserita in seguito).
-% TODO opzioni in formato esteso 
-
 \subsection{Le variabili di ambiente}
 \label{sec:proc_environ}
 
 \subsection{Le variabili di ambiente}
 \label{sec:proc_environ}
 
@@ -1229,7 +1460,7 @@ ambiente, i loro prototipi sono i seguenti:
   \funcdecl{int putenv(char *string)} Aggiunge la stringa \param{string}
   all'ambiente.
   
   \funcdecl{int putenv(char *string)} Aggiunge la stringa \param{string}
   all'ambiente.
   
-  \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e -1 per un
+  \bodydesc{Entrambe le funzioni ritornano 0 in caso di successo e $-1$ per un
     errore, che è sempre \errval{ENOMEM}.}
 \end{functions}
 \noindent la terza, \funcd{unsetenv}, serve a cancellare una variabile di
     errore, che è sempre \errval{ENOMEM}.}
 \end{functions}
 \noindent la terza, \funcd{unsetenv}, serve a cancellare una variabile di
@@ -1300,6 +1531,19 @@ alla cancellazione di tutto l'ambiente per costruirne una versione
 ``\textsl{sicura}'' da zero.
 
 
 ``\textsl{sicura}'' da zero.
 
 
+\subsection{Opzioni in formato esteso}
+\label{sec:proc_opt_extended}
+
+Oltre alla modalità ordinaria di gestione delle opzioni trattata in
+sez.~\ref{sec:proc_opt_handling} le \acr{glibc} forniscono una modalità
+alternativa costituita dalle cosiddette \textit{long-options}, che consente di
+esprimere le opzioni in una forma più descrittiva che nel caso più generale è
+qualcosa del tipo di ``\texttt{-{}-option-name=parameter}''.
+
+(NdA: questa parte verrà inserita in seguito).
+
+% TODO opzioni in formato esteso
+
 \section{Problematiche di programmazione generica}
 \label{sec:proc_gen_prog}
 
 \section{Problematiche di programmazione generica}
 \label{sec:proc_gen_prog}
 
@@ -1687,7 +1931,7 @@ dichiarandole tutte come \direct{volatile}.\footnote{la direttiva
 % LocalWords:  SUCCESS FAILURE void atexit stream fclose unistd descriptor init
 % LocalWords:  SIGCHLD wait function glibc SunOS arg argp execve fig high kb Mb
 % LocalWords:  memory alpha swap table printf Unit MMU paging fault SIGSEGV BSS
 % LocalWords:  SUCCESS FAILURE void atexit stream fclose unistd descriptor init
 % LocalWords:  SIGCHLD wait function glibc SunOS arg argp execve fig high kb Mb
 % LocalWords:  memory alpha swap table printf Unit MMU paging fault SIGSEGV BSS
-% LocalWords:  multitasking segmentation text segment NULL Block Started Symbol
+% LocalWords:  multitasking text segment NULL Block Started Symbol
 % LocalWords:  heap stack calling convention size malloc calloc realloc nmemb
 % LocalWords:  ENOMEM ptr uClib cfree error leak smartpointers hook Dmalloc brk
 % LocalWords:  Gray Watson Electric Fence Bruce Perens sbrk longjmp SUSv BSD ap
 % LocalWords:  heap stack calling convention size malloc calloc realloc nmemb
 % LocalWords:  ENOMEM ptr uClib cfree error leak smartpointers hook Dmalloc brk
 % LocalWords:  Gray Watson Electric Fence Bruce Perens sbrk longjmp SUSv BSD ap
@@ -1701,7 +1945,8 @@ dichiarandole tutte come \direct{volatile}.\footnote{la direttiva
 % LocalWords:  clearenv libc value overwrite string reference result argument
 % LocalWords:  socket variadic ellipsis header stdarg execl self promoting last
 % LocalWords:  float double short register type dest src extern setjmp jmp buf
 % LocalWords:  clearenv libc value overwrite string reference result argument
 % LocalWords:  socket variadic ellipsis header stdarg execl self promoting last
 % LocalWords:  float double short register type dest src extern setjmp jmp buf
-% LocalWords:  env return if while sottoprocesso Di
+% LocalWords:  env return if while Di page cdecl 
+% LocalWords:  environment
 
 %%% Local Variables: 
 %%% mode: latex
 
 %%% Local Variables: 
 %%% mode: latex