Lavoro fatto a casa senza ADSL, correzioni multiple agli indici, documentato
[gapil.git] / process.tex
index 1166f5119bb17c853af906249cc922a7b9cc1592..a0024f55fa18224f479a2a2a1aeecd69e3c3d8f3 100644 (file)
@@ -233,15 +233,15 @@ normalmente un programma 
 
 \begin{figure}[htb]
   \centering
-  \includegraphics[width=14cm]{img/proc_beginend}
+  \includegraphics[width=9cm]{img/proc_beginend}
   \caption{Schema dell'avvio e della conclusione di un programma.}
   \label{fig:proc_prog_start_stop}
 \end{figure}
 
 Si ricordi infine che un programma può anche essere interrotto dall'esterno
 attraverso l'uso di un segnale (modalità di conclusione non mostrata in
-fig.~\ref{fig:proc_prog_start_stop}); torneremo su questo aspetto in
-cap.~\ref{cha:signals}.
+fig.~\ref{fig:proc_prog_start_stop}); tratteremo nei dettagli i segnali e la
+loro gestione nel capitolo \ref{cha:signals}.
 
 
 
@@ -258,15 +258,16 @@ esecuzione, e le varie funzioni utilizzabili per la sua gestione.
 \subsection{I concetti generali}
 \label{sec:proc_mem_gen}
 
-Ci sono vari modi in cui i vari sistemi organizzano la memoria (ed i dettagli
-di basso livello dipendono spesso in maniera diretta dall'architettura
-dell'hardware), ma quello più tipico, usato dai sistemi unix-like come Linux è
-la cosiddetta \textsl{memoria virtuale}\index{memoria~virtuale} che consiste
-nell'assegnare ad ogni processo uno spazio virtuale di indirizzamento lineare,
-in cui gli indirizzi vanno da zero ad un qualche valore massimo.\footnote{nel
-  caso di Linux fino al kernel 2.2 detto massimo era, per macchine a 32bit, di
-  2Gb. Con il kernel 2.4 ed il supporto per la \textit{high-memory} il limite
-  è stato esteso anche per macchine a 32 bit.}
+Ci sono vari modi in cui i sistemi operativi organizzano la memoria, ed i
+dettagli di basso livello dipendono spesso in maniera diretta
+dall'architettura dell'hardware, ma quello più tipico, usato dai sistemi
+unix-like come Linux è la cosiddetta \textsl{memoria
+  virtuale}\index{memoria~virtuale} che consiste nell'assegnare ad ogni
+processo uno spazio virtuale di indirizzamento lineare, in cui gli indirizzi
+vanno da zero ad un qualche valore massimo.\footnote{nel caso di Linux fino al
+  kernel 2.2 detto massimo era, per macchine a 32bit, di 2Gb. Con il kernel
+  2.4 ed il supporto per la \textit{high-memory} il limite è stato esteso
+  anche per macchine a 32 bit.}
 
 Come accennato in cap.~\ref{cha:intro_unix} questo spazio di indirizzi è
 virtuale e non corrisponde all'effettiva posizione dei dati nella RAM del
@@ -274,41 +275,46 @@ computer; in genere detto spazio non 
 indirizzi possibili sono utilizzabili, e quelli usabili non sono
 necessariamente adiacenti).
 
-Per la gestione da parte del kernel la memoria virtuale viene divisa in pagine
-di dimensione fissa (che ad esempio sono di 4kb su macchine a 32 bit e 8kb
-sulle alpha, valori strettamente connessi all'hardware di gestione della
-memoria),\footnote{con le versioni più recenti del kernel è possibile anche
-  utilizzare pagine di dimensioni maggiori, per sistemi con grandi
-  quantitativi di memoria in cui l'uso di pagine troppo piccole comporta una
-  perdita di prestazioni.} e ciascuna pagina della memoria virtuale è
-associata ad un supporto che può essere una pagina di memoria reale o ad un
-dispositivo di stoccaggio secondario (in genere lo spazio disco riservato alla
-swap, o i file che contengono il codice).
-
-Lo stesso pezzo di memoria reale (o di spazio disco) può fare da supporto a
-diverse pagine di memoria virtuale appartenenti a processi diversi (come
-accade in genere per le pagine che contengono il codice delle librerie
-condivise). Ad esempio il codice della funzione \func{printf} starà su una
-sola pagina di memoria reale che farà da supporto a tutte le pagine di memoria
-virtuale di tutti i processi che hanno detta funzione nel loro codice.
-
-La corrispondenza fra le pagine della \index{memoria~virtuale}memoria virtuale
-e quelle della memoria fisica della macchina viene gestita in maniera
-trasparente dal kernel con l'ausilio dell'hardware di gestione della memoria
-(la \textit{Memory Management Unit} del processore).  Poiché in genere la
-memoria fisica è solo una piccola frazione della memoria virtuale, è
-necessario un meccanismo che permetta di trasferire le pagine che servono dal
-supporto su cui si trovano in memoria, eliminando quelle che non servono.
-Questo meccanismo è detto \textsl{paginazione}\index{paginazione} (o
-\textit{paging}), ed è uno dei compiti principali del kernel.
+Per la gestione da parte del kernel la memoria viene divisa in pagine di
+dimensione fissa,\footnote{inizialmente questi erano di 4kb sulle macchine a
+  32 bit e di 8kb sulle alpha, con le versioni più recenti del kernel è
+  possibile anche utilizzare pagine di dimensioni maggiori (4Mb), per sistemi
+  con grandi quantitativi di memoria in cui l'uso di pagine troppo piccole
+  comporta una perdita di prestazioni.} e ciascuna pagina nello spazio di
+indirizzi virtuale è associata ad un supporto che può essere una pagina di
+memoria reale o ad un dispositivo di stoccaggio secondario (come lo spazio
+disco riservato alla swap, o i file che contengono il codice). Per ciasun
+processo il kernel si cura di mantenere un mappa di queste corrispondenze
+nella cosiddetta \itindex{page~table}\textit{page table}.\footnote{questa è
+  una semplificazione brutale, il meccanismo è molto più complesso; una buona
+  trattazione di come Linux gestisce la memoria virtuale si trova su
+  \cite{LinVM}.}
+
+Una stessa pagina di memoria reale può fare da supporto a diverse pagine di
+memoria virtuale appartenenti a processi diversi (come accade in genere per le
+pagine che contengono il codice delle librerie condivise). Ad esempio il
+codice della funzione \func{printf} starà su una sola pagina di memoria reale
+che farà da supporto a tutte le pagine di memoria virtuale di tutti i processi
+che hanno detta funzione nel loro codice.
+
+La corrispondenza fra le pagine della \index{memoria~virtuale} memoria
+virtuale di un processo e quelle della memoria fisica della macchina viene
+gestita in maniera trasparente dal kernel.\footnote{in genere con l'ausilio
+  dell'hardware di gestione della memoria (la \textit{Memory Management Unit}
+  del processore), con i kernel della serie 2.6 è comunque diventato possibile
+  utilizzare Linux anche su architetture che non dispongono di una MMU.}
+Poiché in genere la memoria fisica è solo una piccola frazione della memoria
+virtuale, è necessario un meccanismo che permetta di trasferire le pagine che
+servono dal supporto su cui si trovano in memoria, eliminando quelle che non
+servono.  Questo meccanismo è detto \textsl{paginazione} \index{paginazione}
+(o \textit{paging}), ed è uno dei compiti principali del kernel.
 
 Quando un processo cerca di accedere ad una pagina che non è nella memoria
-reale, avviene quello che viene chiamato un \textit{page
-  fault}\itindex{page~fault}; la gestione della memoria genera un'interruzione
-e passa il controllo al kernel il quale sospende il processo e si incarica di
-mettere in RAM la pagina richiesta (effettuando tutte le operazioni necessarie
-per reperire lo spazio necessario), per poi restituire il controllo al
-processo.
+reale, avviene quello che viene chiamato un \itindex{page~fault} \textit{page
+  fault}; la gestione della memoria genera un'interruzione e passa il
+controllo al kernel il quale sospende il processo e si incarica di mettere in
+RAM la pagina richiesta (effettuando tutte le operazioni necessarie per
+reperire lo spazio necessario), per poi restituire il controllo al processo.
 
 Dal punto di vista di un processo questo meccanismo è completamente
 trasparente, e tutto avviene come se tutte le pagine fossero sempre
@@ -320,7 +326,9 @@ Normalmente questo 
 in genere il sistema è molto efficiente in questo lavoro; quando però ci siano
 esigenze specifiche di prestazioni è possibile usare delle funzioni che
 permettono di bloccare il meccanismo della paginazione\index{paginazione} e
-mantenere fisse delle pagine in memoria (vedi sez.~\ref{sec:proc_mem_lock}).
+mantenere fisse delle pagine in memoria (vedi
+sez.~\ref{sec:proc_mem_lock}). Inoltre per certe applicazioni gli algoritmi di
+gestione della memoria 
 
 
 \subsection{La struttura della memoria di un processo}
@@ -332,31 +340,32 @@ tentativo di accedere ad un indirizzo non allocato 
 commette quando si è manipolato male un puntatore e genera quello che viene
 chiamato un \textit{segmentation fault}. Se si tenta cioè di leggere o
 scrivere da un indirizzo per il quale non esiste un'associazione della pagina
-virtuale, il kernel risponde al relativo \textit{page
-  fault}\itindex{page~fault} mandando un segnale \const{SIGSEGV} al processo,
-che normalmente ne causa la terminazione immediata.
+virtuale, il kernel risponde al relativo \itindex{page~fault} \textit{page
+  fault} mandando un segnale \const{SIGSEGV} al processo, che normalmente ne
+causa la terminazione immediata.
 
 È pertanto importante capire come viene strutturata \textsl{la memoria
-  virtuale}\index{memoria~virtuale} di un processo. Essa viene divisa in
+  virtuale} \index{memoria~virtuale} di un processo. Essa viene divisa in
 \textsl{segmenti}, cioè un insieme contiguo di indirizzi virtuali ai quali il
 processo può accedere.  Solitamente un programma C viene suddiviso nei
 seguenti segmenti:
 
 \begin{enumerate}
-\item Il 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.
+\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 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.
+\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
@@ -378,26 +387,30 @@ seguenti segmenti:
   Storicamente questa seconda parte del segmento dati viene chiamata BSS (da
   \textit{Block Started by Symbol}). La sua dimensione è fissa.
   
-\item Lo \textit{heap}. Tecnicamente lo si può considerare l'estensione del
-  segmento dati, a cui di solito è posto giusto di seguito. È qui che avviene
-  l'allocazione dinamica della memoria; può essere ridimensionato allocando e
-  disallocando la memoria dinamica con le apposite funzioni (vedi
-  sez.~\ref{sec:proc_mem_alloc}), ma il suo limite inferiore (quello adiacente
-  al segmento dati) ha una posizione 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 \textit{stack}, che contiene lo \textit{stack} del
-  programma.  Tutte le volte che si effettua una chiamata ad una funzione è
-  qui che viene salvato l'indirizzo di ritorno e le informazioni dello stato
-  del chiamante (tipo il contenuto di alcuni registri della CPU). Poi la
-  funzione chiamata alloca qui lo spazio per le sue variabili locali: in
-  questo modo le funzioni possono essere chiamate ricorsivamente. Al ritorno
-  della funzione lo spazio è automaticamente rilasciato 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.}
-  
-  La dimensione di questo segmento aumenta seguendo la crescita dello stack
-  del programma, ma non viene ridotta quando quest'ultimo si restringe.
+\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 \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
+
+  La dimensione di questo segmento aumenta seguendo la crescita dello
+  \textit{stack} del programma, ma non viene ridotta quando quest'ultimo si
+  restringe.
 \end{enumerate}
 
 \begin{figure}[htb]
@@ -407,33 +420,34 @@ seguenti segmenti:
   \label{fig:proc_mem_layout}
 \end{figure}
 
-Una disposizione tipica di questi segmenti è 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
+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, a livello di linguaggio, soltanto due modalità di allocazione
-della memoria: l'\textsl{allocazione statica} e l'\textsl{allocazione
-  automatica}.
+Il C supporta direttamente, come linguaggio di programmazione, soltanto due
+modalità di allocazione della memoria: l'\textsl{allocazione statica} e
+l'\textsl{allocazione automatica}.
 
 L'\textsl{allocazione statica} è quella con cui sono memorizzate le variabili
 globali e le variabili statiche, cioè le variabili il cui valore deve essere
 mantenuto per tutta la durata del programma. Come accennato queste variabili
-vengono allocate nel 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.
+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 stack quando viene eseguita la
-funzione e liberato quando si esce dalla medesima.
+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,
@@ -444,10 +458,13 @@ Il C non consente di usare variabili allocate dinamicamente, non 
 cioè definire in fase di programmazione una variabile le cui dimensioni
 possano essere modificate durante l'esecuzione del programma. Per questo le
 librerie del C forniscono una serie opportuna di funzioni per eseguire
-l'allocazione dinamica di memoria (in genere nello heap). Le variabili il
-cui contenuto è allocato in questo modo non potranno essere usate direttamente
-come le altre, ma l'accesso sarà possibile solo in maniera indiretta,
-attraverso dei puntatori.
+l'allocazione dinamica di memoria (in genere nello \itindex{heap} heap). 
+
+Le variabili il cui contenuto è allocato in questo modo non potranno essere
+usate direttamente come le altre (quelle nello \itindex{stack} 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.
 
 
 \subsection{Le funzioni \func{malloc}, \func{calloc}, \func{realloc} e
@@ -576,6 +593,7 @@ programmazione ad oggetti, il problema dei \textit{memory
 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
@@ -615,9 +633,10 @@ molto complesse riguardo l'allocazione della memoria.
 
 Una possibile alternativa all'uso di \func{malloc}, che non soffre dei
 problemi di \textit{memory leak}\itindex{memory~leak} descritti in precedenza,
-è la funzione \funcd{alloca}, che invece di allocare la memoria nello heap usa
-il segmento di stack della funzione corrente. La sintassi è identica a quella
-di \func{malloc}, il suo prototipo è:
+è la funzione \funcd{alloca}, che invece di allocare la memoria 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)}
   Alloca \param{size} byte nello stack.
   
@@ -627,10 +646,10 @@ di \func{malloc}, il suo prototipo 
 \end{prototype}
 
 La funzione alloca la quantità di memoria (non inizializzata) richiesta
-dall'argomento \param{size} nel segmento di 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.
+dall'argomento \param{size} nel segmento di \itindex{stack}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 \textit{memory leak}\itindex{memory~leak},
@@ -681,15 +700,17 @@ prototipo 
 \end{prototype}
 
 La funzione è un'interfaccia diretta all'omonima system call ed imposta
-l'indirizzo finale del 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.
-
-La seconda funzione per la manipolazione delle dimensioni 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 è:
+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.
+
+La seconda funzione per la manipolazione 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.
   
@@ -700,7 +721,7 @@ dati\footnote{in questo caso si tratta soltanto di una funzione di libreria, e
 \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
-segmento dati.
+\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
@@ -712,7 +733,6 @@ standard descritte in precedenza, che sono costruite su di esse.
 
 % TODO documentare \func{madvise}
 % TODO documentare \func{mincore}
-% TODO documentare \func{mprotect} forse da mettere insieme a mmap
 
 \subsection{Il controllo della memoria virtuale}  
 \label{sec:proc_mem_lock}
@@ -781,7 +801,7 @@ 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{capability}\textit{capability}
+privilegi opportuni (la \itindex{capabilities}\textit{capability}
 \const{CAP\_IPC\_LOCK}, vedi sez.~\ref{sec:proc_capabilities}) aveva la
 capacità di bloccare una pagina. 
 
@@ -856,7 +876,7 @@ di indirizzi di un processo.  I prototipi di queste funzioni sono:
   
   \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 la \itindex{capability}\textit{capability}
+    func{munlockall} senza la \itindex{capabilities}\textit{capability}
 \const{CAP\_IPC\_LOCK} genera un errore di \errcode{EPERM}.}
 \end{functions}
 
@@ -871,11 +891,13 @@ costanti:
 \end{basedescript}
 
 Con \func{mlockall} si possono bloccare tutte le pagine mappate nello spazio
-di indirizzi del processo, sia che comprendano il segmento di testo, di dati,
-lo stack, lo 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.
+di indirizzi del processo, sia che comprendano il \index{segmento!dati}
+\index{segmento!testo} segmento di testo, di dati, lo \itindex{stack} stack,
+lo \itindex{heap} 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 sezione critica
 deve provvedere a riservare memoria sufficiente prima dell'ingresso, per
@@ -889,9 +911,12 @@ esecuzione.
 
 In genere si ovvia a questa problematica chiamando una funzione che ha
 allocato una quantità sufficientemente ampia di variabili automatiche, in modo
-che esse vengano mappate in RAM dallo stack, dopo di che, per essere sicuri
-che esse siano state effettivamente portate in memoria, ci si scrive sopra.
-\index{memoria~virtuale|)}
+che esse vengano mappate in RAM dallo \itindex{stack} stack, dopo di che, per
+essere sicuri che esse siano state effettivamente portate in memoria, ci si
+scrive sopra.  
+
+\index{memoria~virtuale|)} 
+
 \itindend{memory~locking}
 
 
@@ -1248,10 +1273,10 @@ versione del vettore \var{environ} questo sar
 corrente sarà deallocata solo se anch'essa è risultante da un'allocazione
 fatta in precedenza da un'altra \func{putenv}. Questo perché il vettore delle
 variabili di ambiente iniziale, creato dalla chiamata ad \func{exec} (vedi
-sez.~\ref{sec:proc_exec}) è piazzato al di sopra dello stack, (vedi
-fig.~\ref{fig:proc_mem_layout}) e non nello heap e non può essere deallocato.
-Inoltre la memoria associata alle variabili di ambiente eliminate non viene
-liberata.
+sez.~\ref{sec:proc_exec}) è piazzato al di sopra dello \itindex{stack} stack,
+(vedi fig.~\ref{fig:proc_mem_layout}) e non nello \itindex{heap} heap e non
+può essere deallocato.  Inoltre la memoria associata alle variabili di
+ambiente eliminate non viene liberata.
 
 L'ultima funzione è \funcd{clearenv}, che viene usata per cancellare
 completamente tutto l'ambiente; il suo prototipo è:
@@ -1374,9 +1399,9 @@ quando la si va a definire. Gli argomenti fissi infatti hanno un loro nome, ma
 quelli variabili vengono indicati in maniera generica dalla \textit{ellipsis}.
 
 L'unica modalità in cui essi possono essere recuperati è pertanto quella
-sequenziale; essi verranno estratti dallo stack secondo l'ordine in cui sono
-stati scritti. Per fare questo in \file{stdarg.h} sono definite delle apposite
-macro; la procedura da seguire è la seguente:
+sequenziale; essi verranno estratti dallo \itindex{stack} stack secondo
+l'ordine in cui sono stati scritti. Per fare questo in \file{stdarg.h} sono
+definite delle apposite macro; la procedura da seguire è la seguente:
 \begin{enumerate}
 \item Inizializzare un puntatore alla lista degli argomenti di tipo
   \macro{va\_list} attraverso la macro \macro{va\_start}.
@@ -1432,8 +1457,8 @@ argomenti e poter memorizzare una posizione durante la stessa.  La cosa pi
 naturale in questo caso sembrerebbe quella di copiarsi il puntatore alla lista
 degli argomenti con una semplice assegnazione. Dato che una delle
 realizzazioni più comuni di \macro{va\_list} è quella di un puntatore nello
-stack all'indirizzo dove sono stati salvati gli argomenti, è assolutamente
-normale pensare di poter effettuare questa operazione.
+\itindex{stack} stack all'indirizzo dove sono stati salvati gli argomenti, è
+assolutamente normale pensare di poter effettuare questa operazione.
 
 In generale però possono esistere anche realizzazioni diverse, per questo
 motivo \macro{va\_list} è definito come \textsl{tipo opaco}\index{tipo!opaco}
@@ -1486,9 +1511,9 @@ come ultimo argomento (come fa ad esempio \func{execl} che usa un puntatore
 Uno dei possibili problemi che si possono avere con le subroutine è quello di
 restituire alla funzione chiamante dei dati che sono contenuti in una
 variabile automatica.  Ovviamente quando la subroutine ritorna la sezione
-dello stack che conteneva la variabile automatica potrà essere riutilizzata da
-una nuova funzione, con le immaginabili conseguenze di sovrapposizione e
-sovrascrittura dei dati.
+dello \itindex{stack} stack che conteneva la variabile automatica potrà essere
+riutilizzata da una nuova funzione, con le immaginabili conseguenze di
+sovrapposizione e sovrascrittura dei dati.
 
 Per questo una delle regole fondamentali della programmazione in C è che
 all'uscita di una funzione non deve restare nessun riferimento alle variabili
@@ -1534,10 +1559,11 @@ scartando l'input come errato.\footnote{a meno che, come precisa \cite{glibc},
   essere eseguite con un salto non-locale.}
 
 Tutto ciò può essere realizzato proprio con un salto non-locale; questo di
-norma viene realizzato salvando il contesto dello stack nel punto in cui si
-vuole tornare in caso di errore, e ripristinandolo, in modo da tornare nella
-funzione da cui si era partiti, quando serve.  La funzione che permette di
-salvare il contesto dello stack è \funcd{setjmp}, il cui prototipo è:
+norma viene realizzato salvando il contesto dello \itindex{stack} stack nel
+punto in cui si vuole tornare in caso di errore, e ripristinandolo, in modo da
+tornare nella funzione da cui si era partiti, quando serve.  La funzione che
+permette di salvare il contesto dello \itindex{stack} stack è \funcd{setjmp},
+il cui prototipo è:
 \begin{functions}
   \headdecl{setjmp.h}
   \funcdecl{int setjmp(jmp\_buf env)}
@@ -1549,8 +1575,8 @@ salvare il contesto dello stack 
     che usa il contesto salvato in precedenza.}
 \end{functions}
   
-Quando si esegue la funzione il contesto corrente dello stack viene salvato
-nell'argomento \param{env}, una variabile di tipo
+Quando si esegue la funzione il contesto corrente dello \itindex{stack} stack
+viene salvato nell'argomento \param{env}, una variabile di tipo
 \type{jmp\_buf}\footnote{questo è un classico esempio di variabile di
   \textsl{tipo opaco}\index{tipo!opaco}. Si definiscono così strutture ed
   altri oggetti usati da una libreria, la cui struttura interna non deve
@@ -1563,10 +1589,10 @@ essere viste in tutte le funzioni del programma.
 Quando viene eseguita direttamente la funzione ritorna sempre zero, un valore
 diverso da zero viene restituito solo quando il ritorno è dovuto ad una
 chiamata di \func{longjmp} in un'altra parte del programma che ripristina lo
-stack effettuando il salto non-locale. Si tenga conto che il contesto salvato
-in \param{env} viene invalidato se la routine che ha chiamato \func{setjmp}
-ritorna, nel qual caso un successivo uso di \func{longjmp} può comportare
-conseguenze imprevedibili (e di norma fatali) per il processo.
+\itindex{stack} stack effettuando il salto non-locale. Si tenga conto che il
+contesto salvato in \param{env} viene invalidato se la routine che ha chiamato
+\func{setjmp} ritorna, nel qual caso un successivo uso di \func{longjmp} può
+comportare conseguenze imprevedibili (e di norma fatali) per il processo.
   
 Come accennato per effettuare un salto non-locale ad
 un punto precedentemente stabilito con \func{setjmp} si usa la funzione
@@ -1580,12 +1606,13 @@ un punto precedentemente stabilito con \func{setjmp} si usa la funzione
   \bodydesc{La funzione non ritorna.}
 \end{functions}
 
-La funzione ripristina il contesto dello stack salvato da una chiamata a
-\func{setjmp} nell'argomento \param{env}. Dopo l'esecuzione della funzione il
-programma prosegue nel codice successivo al ritorno della \func{setjmp} con
-cui si era salvato \param{env}, che restituirà il valore \param{val} invece di
-zero.  Il valore di \param{val} specificato nella chiamata deve essere diverso
-da zero, se si è specificato 0 sarà comunque restituito 1 al suo posto.
+La funzione ripristina il contesto dello \itindex{stack} stack salvato da una
+chiamata a \func{setjmp} nell'argomento \param{env}. Dopo l'esecuzione della
+funzione il programma prosegue nel codice successivo al ritorno della
+\func{setjmp} con cui si era salvato \param{env}, che restituirà il valore
+\param{val} invece di zero.  Il valore di \param{val} specificato nella
+chiamata deve essere diverso da zero, se si è specificato 0 sarà comunque
+restituito 1 al suo posto.
 
 In sostanza un \func{longjmp} è analogo ad un \code{return}, solo che invece
 di ritornare alla riga successiva della funzione chiamante, il programma
@@ -1594,10 +1621,11 @@ il ritorno pu
 annidate.
 
 L'implementazione di queste funzioni comporta alcune restrizioni dato che esse
-interagiscono direttamente con la gestione dello stack ed il funzionamento del
-compilatore stesso. In particolare \func{setjmp} è implementata con una macro,
-pertanto non si può cercare di ottenerne l'indirizzo, ed inoltre delle
-chiamate a questa funzione sono sicure solo in uno dei seguenti casi:
+interagiscono direttamente con la gestione dello \itindex{stack} stack ed il
+funzionamento del compilatore stesso. In particolare \func{setjmp} è
+implementata con una macro, pertanto non si può cercare di ottenerne
+l'indirizzo, ed inoltre delle chiamate a questa funzione sono sicure solo in
+uno dei seguenti casi:
 \begin{itemize}
 \item come espressione di controllo in un comando condizionale, di selezione
   o di iterazione (come \code{if}, \code{switch} o \code{while});
@@ -1631,17 +1659,18 @@ delle variabili automatiche (o di quelle dichiarate
 Quello che succede infatti è che i valori delle variabili che sono tenute in
 memoria manterranno il valore avuto al momento della chiamata di
 \func{longjmp}, mentre quelli tenuti nei registri del processore (che nella
-chiamata ad un'altra funzione vengono salvati nel contesto nello stack)
-torneranno al valore avuto al momento della chiamata di \func{setjmp}; per
-questo quando si vuole avere un comportamento coerente si può bloccare
-l'ottimizzazione che porta le variabili nei registri dichiarandole tutte come
-\direct{volatile}\footnote{la direttiva \direct{volatile} informa il
-  compilatore che la variabile che è dichiarata può essere modificata, durante
-  l'esecuzione del nostro, da altri programmi. Per questo motivo occorre dire
-  al compilatore che non deve essere mai utilizzata l'ottimizzazione per cui
-  quanto opportuno essa viene mantenuta in un registro, poiché in questo modo
-  si perderebbero le eventuali modifiche fatte dagli altri programmi (che
-  avvengono solo in una copia posta in memoria).}.
+chiamata ad un'altra funzione vengono salvati nel contesto nello
+\itindex{stack} stack) torneranno al valore avuto al momento della chiamata di
+\func{setjmp}; per questo quando si vuole avere un comportamento coerente si
+può bloccare l'ottimizzazione che porta le variabili nei registri
+dichiarandole tutte come \direct{volatile}\footnote{la direttiva
+  \direct{volatile} informa il compilatore che la variabile che è dichiarata
+  può essere modificata, durante l'esecuzione del nostro, da altri programmi.
+  Per questo motivo occorre dire al compilatore che non deve essere mai
+  utilizzata l'ottimizzazione per cui quanto opportuno essa viene mantenuta in
+  un registro, poiché in questo modo si perderebbero le eventuali modifiche
+  fatte dagli altri programmi (che avvengono solo in una copia posta in
+  memoria).}.
 
 \index{salto~non-locale|)}