%% process.tex
%%
-%% Copyright (C) 2000-2015 by Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2018 by 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",
variabili proprie e sarà eseguito in maniera completamente indipendente da
tutti gli altri. 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 in cap.~\ref{cha:threads}.
+trattata a parte\unavref{in cap.~\ref{cha:threads}}.
\subsection{L'avvio e l'esecuzione di un programma}
\itindbeg{link-loader}
\itindbeg{shared~objects}
-Quando un programma viene messo in esecuzione cosa che può essere fatta solo
-con una funzione della famiglia \func{exec} (vedi sez.~\ref{sec:proc_exec}) il
-kernel esegue un opportuno codice di avvio, il cosiddetto
+Quando un programma viene messo in esecuzione, cosa che può essere fatta solo
+con una funzione della famiglia \func{exec} (vedi sez.~\ref{sec:proc_exec}),
+il kernel esegue un opportuno codice di avvio, il cosiddetto
\textit{link-loader}, costituito dal programma \cmd{ld-linux.so}. Questo
programma è una parte fondamentale del sistema il cui compito è quello della
gestione delle cosiddette \textsl{librerie condivise}, quelle che nel mondo
Questo significa però che normalmente il codice di un programma è incompleto,
contenendo solo i riferimenti alle funzioni di libreria che vuole utilizzare e
non il relativo codice. Per questo motivo all'avvio del programma è necessario
-l'intervento del \textit{link-loader} il cui compito è
-caricare in memoria le librerie condivise eventualmente assenti, ed effettuare
-poi il collegamento dinamico del codice del programma alle funzioni di
-libreria da esso utilizzate prima di metterlo in esecuzione.
+l'intervento del \textit{link-loader} il cui compito è caricare in memoria le
+librerie condivise eventualmente assenti, ed effettuare poi il collegamento
+dinamico del codice del programma alle funzioni di libreria da esso utilizzate
+prima di metterlo in esecuzione.
Il funzionamento di \cmd{ld-linux.so} è controllato da alcune variabili di
-ambiente e dal contenuto del file \conffile{/etc/ld.so.conf}, che consentono
-di elencare le directory un cui cercare le librerie e determinare quali
-verranno utilizzate. In particolare con la variabile di ambiente
+ambiente e dal contenuto del file \conffile{/etc/ld.so.conf} che consentono di
+elencare le directory un cui cercare le librerie e determinare quali verranno
+utilizzate. In particolare con la variabile di ambiente
\envvar{LD\_LIBRARY\_PATH} si possono indicare ulteriori directory rispetto a
quelle di sistema in cui inserire versioni personali delle librerie che hanno
la precedenza su quelle di sistema, mentre con la variabile di ambiente
& ANSI C& POSIX& \\
\hline
\hline
- \headfile{assert.h}&$\bullet$& -- & Verifica le asserzioni fatte in un
- programma.\\
- \headfile{ctype.h} &$\bullet$& -- & Tipi standard.\\
- \headfile{dirent.h}& -- &$\bullet$& Manipolazione delle directory.\\
- \headfile{errno.h} & -- &$\bullet$& Errori di sistema.\\
- \headfile{fcntl.h} & -- &$\bullet$& Controllo sulle opzioni dei file.\\
- \headfile{limits.h}& -- &$\bullet$& Limiti e parametri del sistema.\\
- \headfile{malloc.h}&$\bullet$& -- & Allocazione della memoria.\\
- \headfile{setjmp.h}&$\bullet$& -- & Salti non locali.\\
- \headfile{signal.h}& -- &$\bullet$& Gestione dei segnali.\\
- \headfile{stdarg.h}&$\bullet$& -- & Gestione di funzioni a argomenti
+ \headfiled{assert.h}&$\bullet$& -- & Verifica le asserzioni fatte in un
+ programma.\\
+ \headfiled{ctype.h} &$\bullet$& -- & Tipi standard.\\
+ \headfiled{dirent.h}& -- &$\bullet$& Manipolazione delle directory.\\
+ \headfiled{errno.h} & -- &$\bullet$& Errori di sistema.\\
+ \headfiled{fcntl.h} & -- &$\bullet$& Controllo sulle opzioni dei
+ file.\\
+ \headfiled{limits.h}& -- &$\bullet$& Limiti e parametri del sistema.\\
+ \headfiled{malloc.h}&$\bullet$& -- & Allocazione della memoria.\\
+ \headfiled{setjmp.h}&$\bullet$& -- & Salti non locali.\\
+ \headfiled{signal.h}& -- &$\bullet$& Gestione dei segnali.\\
+ \headfiled{stdarg.h}&$\bullet$& -- & Gestione di funzioni a argomenti
variabili.\\
- \headfile{stdio.h} &$\bullet$& -- & I/O bufferizzato in standard ANSI
- C.\\
- \headfile{stdlib.h}&$\bullet$& -- & Definizioni della libreria
- standard.\\
- \headfile{string.h}&$\bullet$& -- & Manipolazione delle stringhe.\\
- \headfile{time.h} & -- &$\bullet$& Gestione dei tempi.\\
- \headfile{times.h} &$\bullet$& -- & Gestione dei tempi.\\
- \headfile{unistd.h}& -- &$\bullet$& Unix standard library.\\
- \headfile{utmp.h} & -- &$\bullet$& Registro connessioni utenti.\\
+ \headfiled{stdio.h} &$\bullet$& -- & I/O bufferizzato in standard ANSI
+ C.\\
+ \headfiled{stdlib.h}&$\bullet$& -- & Definizioni della libreria
+ standard.\\
+ \headfiled{string.h}&$\bullet$& -- & Manipolazione delle stringhe.\\
+ \headfiled{time.h} & -- &$\bullet$& Gestione dei tempi.\\
+ \headfiled{times.h} &$\bullet$& -- & Gestione dei tempi.\\
+ \headfiled{unistd.h}& -- &$\bullet$& Unix standard library.\\
+ \headfiled{utmp.h} & -- &$\bullet$& Registro connessioni utenti.\\
\hline
\end{tabular}
\caption{Elenco dei principali \textit{header file} definiti dagli standard
segue le specifiche del \textit{Filesystem Hierarchy Standard} (per maggiori
informazioni si consulti sez.~1.2.3 di \cite{AGL}) si trovano sotto
\texttt{/usr/include}.} o fra virgolette, nel qual caso si fa riferimento
-ad una versione locale, da indicare con un \itindsub{pathname}{relativo}
-\textit{pathname} relativo:
+ad una versione locale, da indicare con un \textit{pathname} relativo:
\includecodesnip{listati/main_include.c}
Si tenga presente che oltre ai nomi riservati a livello generale di cui si è
``\texttt{TC}'' e con ``\texttt{B}'' seguito da un numero,
\item in \headfile{grp.h} vengono riservati i nomi che iniziano con
``\texttt{gr\_}'',
-\item in \headfile{pwd.h}vengono riservati i nomi che iniziano con
+\item in \headfile{pwd.h} vengono riservati i nomi che iniziano con
``\texttt{pw\_}'',
\end{itemize*}
nell'esecuzione del programma. Una funzione ordinaria infatti viene eseguita,
esattamente come il codice che si è scritto nel corpo del programma, in
\textit{user space}. Quando invece si esegue una \textit{system call}
-l'esecuzione ordinaria del programma viene interrotta, i dati forniti (come
-argomenti della chiamata) vengono trasferiti al kernel che esegue il codice
-della \textit{system call} (che è codice del kernel) in \textit{kernel space}.
+l'esecuzione ordinaria del programma viene interrotta con quello che viene
+usualmente chiamato un \itindex{context~switch} \textit{context
+ switch};\footnote{in realtà si parla più comunemente di \textit{context
+ switch} quando l'esecuzione di un processo viene interrotta dal kernel
+ (tramite lo \textit{scheduler}) per metterne in esecuzione un altro, ma il
+ concetto generale resta lo stesso: l'esecuzione del proprio codice in
+ \textit{user space} viene interrotta e lo stato del processo deve essere
+ salvato per poterne riprendere l'esecuzione in un secondo tempo.} il
+contesto di esecuzione del processo viene salvato in modo da poterne
+riprendere in seguito l'esecuzione ed i dati forniti (come argomenti della
+chiamata) vengono trasferiti al kernel che esegue il codice della
+\textit{system call} (che è codice del kernel) in \textit{kernel space}; al
+completamento della \textit{system call} i dati salvati nel \textit{context
+ switch} saranno usati per riprendere l'esecuzione ordinaria del programma.
Dato che il passaggio dei dati ed il salvataggio del contesto di esecuzione
-del programma che consentirà di riprenderne l'esecuzione ordinaria al
-completamento della \textit{system call} sono operazioni critiche per le
-prestazioni del sistema, per rendere il più veloce possibile questa
-operazione, usualmente chiamata \textit{context switch} sono state sviluppate
-una serie di ottimizzazioni che richiedono alcune preparazioni abbastanza
-complesse dei dati, che in genere dipendono dall'architettura del processore
-sono scritte direttamente in \textit{assembler}.
+sono operazioni critiche per le prestazioni del sistema, per rendere il più
+veloce possibile questa operazione sono state sviluppate una serie di
+ottimizzazioni che richiedono alcune preparazioni abbastanza complesse dei
+dati, che in genere dipendono dall'architettura del processore e sono scritte
+direttamente in \textit{assembler}.
+
%
% TODO:trattare qui, quando sarà il momento vsyscall e vDSO, vedi:
può voler utilizzare una \textit{system call} che non è stata ancora associata
ad una funzione di libreria. In tal caso, per evitare di dover effettuare
esplicitamente le operazioni di preparazione citate, all'interno della
-\textsl{glibc} è fornita una specifica funzione, \funcd{syscall}, che consente
-eseguire direttamente una \textit{system call}; il suo prototipo, accessibile
-se si è definita la macro \macro{\_GNU\_SOURCE}, è:
+\textsl{glibc} è fornita una specifica funzione,
+\funcd{syscall},\footnote{fino a prima del kernel 2.6.18 per l'esecuzione
+ diretta delle \textit{system call} erano disponibili anche una serie di
+ macro \texttt{\_syscall\textsl{N}} (con $N$ pari al numero di argomenti
+ della \textit{system call}); queste sono deprecate e pertanto non ne
+ parleremo ulteriormente.} che consente eseguire direttamente una
+\textit{system call}; il suo prototipo, accessibile se si è definita la macro
+\macro{\_GNU\_SOURCE}, è:
\begin{funcproto}{
\fhead{unistd.h}
\fhead{sys/syscall.h}
- \fdecl{int syscall(int number, ...)}
+ \fdecl{long syscall(int number, ...)}
\fdesc{Esegue la \textit{system call} indicata da \param{number}.}
}
{La funzione ritorna un intero dipendente dalla \textit{system call} invocata,
ciascuna \textit{system call} viene in genere identificata da una costante
nella forma \texttt{SYS\_*} dove al prefisso viene aggiunto il nome che spesso
corrisponde anche alla omonima funzione di libreria. Queste costanti sono
-definite nel file \headfile{sys/syscall.h}, ma si possono anche usare
+definite nel file \headfiled{sys/syscall.h}, ma si possono anche usare
direttamente valori numerici.
chiusura invocando direttamente la funzione \func{exit}. Queste due modalità
sono assolutamente equivalenti, dato che \func{exit} viene chiamata in maniera
trasparente anche quando \code{main} ritorna, passandogli come argomento il
-valore di ritorno (che essendo .
+valore di ritorno.
La funzione \funcd{exit}, che è completamente generale, essendo definita dallo
standard ANSI C, è quella che deve essere invocata per una terminazione
verrebbe interpretato come un successo.
Per questo motivo in \headfile{stdlib.h} sono definite, seguendo lo standard
-POSIX, le due costanti \const{EXIT\_SUCCESS} e \const{EXIT\_FAILURE}, da usare
-sempre per specificare lo stato di uscita di un processo. Su Linux, ed in
-generale in qualunque sistema POSIX, ad esse sono assegnati rispettivamente i
-valori 0 e 1.
+POSIX, le due costanti \constd{EXIT\_SUCCESS} e \constd{EXIT\_FAILURE}, da
+usare sempre per specificare lo stato di uscita di un processo. Su Linux, ed
+in generale in qualunque sistema POSIX, ad esse sono assegnati rispettivamente
+i valori 0 e 1.
\itindend{exit~status}
Una forma alternativa per effettuare una terminazione esplicita di un
programma è quella di chiamare direttamente la \textit{system call}
\funcd{\_exit},\footnote{la stessa è definita anche come \funcd{\_Exit} in
- \headfile{stdlib.h}.} che restituisce il controllo direttamente al kernel,
-concludendo immediatamente il processo, il suo prototipo è:
+ \headfile{stdlib.h}, inoltre a partire dalle \acr{glibc} 2.3 usando questa
+ funzione viene invocata \func{exit\_group} che termina tutti i
+ \textit{thread} del processo e non solo quello corrente (fintanto che non si
+ usano i \textit{thread}\unavref{, vedi sez.~\ref{cha:threads},} questo non
+ fa nessuna differenza).} che restituisce il controllo direttamente al
+kernel, concludendo immediatamente il processo, il suo prototipo è:
\begin{funcproto}{ \fhead{unistd.h} \fdecl{void \_exit(int status)}
\fdesc{Causa la conclusione immediata del programma.} } {La funzione non
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,\footnote{nel caso di \func{atexit} lo standard POSIX.1-2001
- richiede che siano registrabili almeno \const{ATEXIT\_MAX} funzioni (il
+ richiede che siano registrabili almeno \constd{ATEXIT\_MAX} funzioni (il
valore può essere ottenuto con \func{sysconf}, vedi
sez.~\ref{sec:sys_limits}).} sia per la chiamata ad \func{exit} che per il
ritorno di \code{main}. La prima funzione che si può utilizzare a tal fine è
anche utilizzare pagine di dimensioni maggiori (di 4Mb, dette \textit{huge
page}), per sistemi con grandi quantitativi di memoria in cui l'uso di
pagine troppo piccole comporta una perdita di prestazioni. In alcuni sistemi
-la costante \const{PAGE\_SIZE}, definita in \headfile{limits.h}, indica la
+la costante \constd{PAGE\_SIZE}, definita in \headfile{limits.h}, indica la
dimensione di una pagina in byte, con Linux questo non avviene e per ottenere
questa dimensione si deve ricorrere alla funzione \func{getpagesize} (vedi
sez.~\ref{sec:sys_memory_res}).
indirizzi virtuali ai quali il processo può accedere. Solitamente un
programma C viene suddiviso nei seguenti segmenti:
\index{segmento!testo|(}
-\index{segmento!dati(}
+\index{segmento!dati|(}
\itindbeg{heap}
\itindbeg{stack}
-\begin{enumerate*}
+\begin{enumerate}
\item Il \textsl{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
globale è che essa può essere vista solo all'interno della funzione in cui
è dichiarata.} e la memoria allocata dinamicamente. Di norma è diviso in
tre parti:
- \begin{itemize*}
+ \begin{itemize}
\item Il segmento dei dati inizializzati, che contiene le variabili il cui
valore è stato assegnato esplicitamente. Ad esempio se si definisce:
\includecodesnip{listati/pi.c}
disallocare la memoria dinamica con le apposite funzioni (vedi
sez.~\ref{sec:proc_mem_alloc}), ma il suo limite inferiore, quello
adiacente al segmento dei dati non inizializzati, ha una posizione fissa.
- \end{itemize*}
+ \end{itemize}
\item Il segmento di \textit{stack}, che contiene quello che viene chiamato 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
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*}
+\end{enumerate}
\begin{figure}[htb]
\centering
inizializzato a zero al caricamento del programma.
\index{segmento!testo|)}
-\index{segmento!dati)}
+\index{segmento!dati|)}
\itindend{heap}
\itindend{stack}
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 funzione
che contiene l'errore. Per questo motivo è sempre molto difficile trovare un
-\textit{memory leak}.
-
-In C e C++ il problema è particolarmente sentito. In C++, per mezzo della
-programmazione ad oggetti, il problema dei \textit{memory leak} si può
-notevolmente ridimensionare 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.
+\textit{memory leak}. In C e C++ il problema è particolarmente sentito. In
+C++, per mezzo della programmazione ad oggetti, il problema dei \textit{memory
+ leak} si può notevolmente ridimensionare 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
+% \itindex{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
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
+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
\textit{segment violation} la prima volta che cercherà di accedere alla
memoria non effettivamente disponibile.
-
\index{segmento!dati|(}
\itindbeg{heap}
La funzione è un'interfaccia all'omonima \textit{system call} ed imposta
l'indirizzo finale del segmento dati di un processo (più precisamente dello
\textit{heap}) all'indirizzo specificato da \param{addr}. Quest'ultimo deve
-essere un valore ragionevole, e la dimensione totale non deve comunque
-eccedere un eventuale limite (vedi sez.~\ref{sec:sys_resource_limit}) imposto
-sulle dimensioni massime del segmento dati del processo.
+essere un valore ragionevole e la dimensione totale non deve comunque eccedere
+un eventuale limite (vedi sez.~\ref{sec:sys_resource_limit}) sulle dimensioni
+massime del segmento dati del processo.
Il valore di ritorno della funzione fa riferimento alla versione fornita dalla
\acr{glibc}, in realtà in Linux la \textit{system call} corrispondente
caso \var{errno} assumerà il valore \errcode{ENOMEM}.}
\end{funcproto}
-La funzione incrementa la dimensione dello \textit{heap} di un
-programma del valore indicato dall'argomento \param{increment}, restituendo il
-nuovo indirizzo finale dello stesso. L'argomento è definito come di tipo
-\type{intptr\_t}, ma a seconda della versione delle librerie e del sistema può
-essere indicato con una serie di tipi equivalenti come \ctyp{ptrdiff\_t},
-\ctyp{ssize\_t}, \ctyp{int}. Se invocata con un valore nullo la funzione
+La funzione incrementa la dimensione dello \textit{heap} di un programma del
+valore indicato dall'argomento \param{increment}, restituendo il nuovo
+indirizzo finale dello stesso. L'argomento è definito come di tipo
+\typed{intptr\_t}, ma a seconda della versione delle librerie e del sistema
+può essere indicato con una serie di tipi equivalenti come \type{ptrdiff\_t},
+\type{ssize\_t}, \ctyp{int}. Se invocata con un valore nullo la funzione
permette di ottenere l'attuale posizione della fine del segmento dati.
Queste due funzioni sono state deliberatamente escluse dallo standard POSIX.1
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 \headfile{unistd.h} la macro
-\macro{\_POSIX\_MEMLOCK\_RANGE} per indicare la capacità di eseguire il
+\macrod{\_POSIX\_MEMLOCK\_RANGE} per indicare la capacità di eseguire il
\textit{memory locking}.
Siccome la richiesta di un \textit{memory lock} da parte di un processo riduce
pagine di memoria, pertanto se si ha a cuore la portabilità si deve avere cura
di allinearne correttamente il valore.
+% TODO trattare mlock2, introdotta con il kernel 4.4 (vedi
+% http://lwn.net/Articles/650538/)
+
Altre due funzioni di sistema, \funcd{mlockall} e \funcd{munlockall},
consentono di bloccare genericamente la paginazione per l'intero spazio di
indirizzi di un processo. I prototipi di queste funzioni sono:
\textbf{Valore} & \textbf{Significato} \\
\hline
\hline
- \const{MCL\_CURRENT}& blocca tutte le pagine correntemente mappate nello
- spazio di indirizzi del processo.\\
- \const{MCL\_FUTURE} & blocca tutte le pagine che verranno mappate nello
- spazio di indirizzi del processo.\\
+ \constd{MCL\_CURRENT}& blocca tutte le pagine correntemente mappate nello
+ spazio di indirizzi del processo.\\
+ \constd{MCL\_FUTURE} & blocca tutte le pagine che verranno mappate nello
+ spazio di indirizzi del processo.\\
\hline
\end{tabular}
\caption{Valori e significato dell'argomento \param{flags} della funzione
\textbf{Valore} & \textbf{Significato} \\
\hline
\hline
- \const{MCHECK\_OK} & Riportato a \func{mprobe} se nessuna
- inconsistenza è presente.\\
- \const{MCHECK\_DISABLED}& Riportato a \func{mprobe} se si è chiamata
- \func{mcheck} dopo aver già usato
- \func{malloc}.\\
- \const{MCHECK\_HEAD} & I dati immediatamente precedenti il buffer sono
- stati modificati, avviene in genere quando si
- decrementa eccessivamente il valore di un
- puntatore scrivendo poi prima dell'inizio del
- buffer.\\
- \const{MCHECK\_TAIL} & I dati immediatamente seguenti il buffer sono
- stati modificati, succede quando si va scrivere
- oltre la dimensione corretta del buffer.\\
- \const{MCHECK\_FREE} & Il buffer è già stato disallocato.\\
+ \constd{MCHECK\_OK} & Riportato a \func{mprobe} se nessuna
+ inconsistenza è presente.\\
+ \constd{MCHECK\_DISABLED}& Riportato a \func{mprobe} se si è chiamata
+ \func{mcheck} dopo aver già usato
+ \func{malloc}.\\
+ \constd{MCHECK\_HEAD} & I dati immediatamente precedenti il buffer sono
+ stati modificati, avviene in genere quando si
+ decrementa eccessivamente il valore di un
+ puntatore scrivendo poi prima dell'inizio del
+ buffer.\\
+ \constd{MCHECK\_TAIL} & I dati immediatamente seguenti il buffer sono
+ stati modificati, succede quando si va scrivere
+ oltre la dimensione corretta del buffer.\\
+ \constd{MCHECK\_FREE} & Il buffer è già stato disallocato.\\
\hline
\end{tabular}
\caption{Valori dello stato dell'allocazione di memoria ottenibili dalla
opzioni sono spostati in coda al vettore. Oltre a questa esistono altre due
modalità di gestire gli elementi di \param{argv}; se \param{optstring} inizia
con il carattere ``\texttt{+}'' (o è impostata la variabile di ambiente
-\macro{POSIXLY\_CORRECT}) la scansione viene fermata non appena si incontra un
+\cmd{POSIXLY\_CORRECT}) la scansione viene fermata non appena si incontra un
elemento che non è un'opzione.
L'ultima modalità, usata quando un programma può gestire la mescolanza fra
\subsection{Il passaggio di un numero variabile di argomenti}
\label{sec:proc_variadic}
-\index{funzioni!variadic|(}
+\index{funzioni!\textit{variadic}|(}
Come vedremo nei capitoli successivi, non sempre è possibile specificare un
numero fisso di argomenti per una funzione. Lo standard ISO C prevede nella
pertanto quella sequenziale, in cui vengono estratti dallo \textit{stack}
secondo l'ordine in cui sono stati scritti nel prototipo della funzione.
+\macrobeg{va\_start}
+
Per fare questo in \headfile{stdarg.h} sono definite delle macro specifiche,
previste dallo standard ISO C89, che consentono di eseguire questa operazione.
La prima di queste macro è \macro{va\_start}, che inizializza opportunamente
}
\end{funcbox}}
-La macro inizializza il puntatore alla lista di argomenti \param{ap} che
-deve essere una apposita variabile di tipo \type{va\_list}; il
+La macro inizializza il puntatore alla lista di argomenti \param{ap} che deve
+essere una apposita variabile di tipo \type{va\_list}; il
parametro \param{last} deve indicare il nome dell'ultimo degli argomenti fissi
-dichiarati nel prototipo della funzione \textit{variadic}.
+dichiarati nel prototipo della funzione \textit{variadic}.
+
+\macrobeg{va\_arg}
La seconda macro di gestione delle liste di argomenti di una funzione
\textit{variadic} è \macro{va\_arg}, che restituisce in successione un
risultati indefiniti anche quando si chiama \macro{va\_arg} specificando un
tipo che non corrisponde a quello usato per il corrispondente argomento.
+\macrobeg{va\_end}
+
Infine una volta completata l'estrazione occorre indicare che si sono concluse
-le operazioni con la macro \macro{va\_end}, la cui definizione è:
+le operazioni con la macro \macrod{va\_end}, la cui definizione è:
{\centering
\begin{funcbox}{
(anche se non si era completata l'estrazione) dato che il valore di \param{ap}
risulterebbe indefinito.
+\macroend{va\_start}
+\macroend{va\_arg}
+\macroend{va\_end}
+
Esistono dei casi in cui è necessario eseguire più volte la scansione degli
argomenti e poter memorizzare una posizione durante la stessa. In questo caso
sembrerebbe naturale copiarsi la lista degli argomenti \param{ap} con una
\index{tipo!opaco|(}
In generale però possono esistere anche realizzazioni diverse, ed è per questo
-motivo che invece che di un semplice puntatore viene \type{va\_list} è quello
-che viene chiamato un \textsl{tipo opaco}. Si chiamano così quei tipi di dati,
-in genere usati da una libreria, la cui struttura interna non deve essere
-vista dal programma chiamante (da cui deriva il nome opaco) che li devono
-utilizzare solo attraverso dalle opportune funzioni di gestione.
+motivo che invece che un semplice puntatore, \typed{va\_list} è quello che
+viene chiamato un \textsl{tipo opaco}. Si chiamano così quei tipi di dati, in
+genere usati da una libreria, la cui struttura interna non deve essere vista
+dal programma chiamante (da cui deriva il nome opaco) che li devono utilizzare
+solo attraverso dalle opportune funzioni di gestione.
\index{tipo!opaco|)}
-Per questo motivo una variabile di tipo \type{va\_list} non può essere
+Per questo motivo una variabile di tipo \typed{va\_list} non può essere
assegnata direttamente ad un'altra variabile dello stesso tipo, ma lo standard
ISO C99\footnote{alcuni sistemi che non hanno questa macro provvedono al suo
- posto \macro{\_\_va\_copy} che era il nome proposto in una bozza dello
+ posto \macrod{\_\_va\_copy} che era il nome proposto in una bozza dello
standard.} ha previsto una macro ulteriore che permette di eseguire la
copia di una lista degli argomenti:
La macro copia l'attuale della lista degli argomenti \param{src} su una nuova
lista \param{dest}. Anche in questo caso è buona norma chiudere ogni
-esecuzione di una \macro{va\_copy} con una corrispondente \macro{va\_end} sul
+esecuzione di una \macrod{va\_copy} con una corrispondente \macro{va\_end} sul
nuovo puntatore alla lista degli argomenti.
La chiamata di una funzione con un numero variabile di argomenti, posto che la
usa un puntatore \val{NULL} per indicare la fine della lista degli argomenti
(vedi sez.~\ref{sec:proc_exec}).
-\index{funzioni!variadic|)}
+\index{funzioni!\textit{variadic}|)}
\subsection{Il controllo di flusso non locale}
\label{sec:proc_longjmp}
Quando si esegue la funzione il contesto corrente dello \textit{stack} viene
salvato nell'argomento \param{env}, una variabile di tipo
-\type{jmp\_buf}\footnote{anche questo è un classico esempio di variabile di
+\typed{jmp\_buf}\footnote{anche questo è un classico esempio di variabile di
\textsl{tipo opaco}.} che deve essere stata definita in precedenza. In
genere le variabili di tipo \type{jmp\_buf} vengono definite come variabili
globali in modo da poter essere viste in tutte le funzioni del programma.
specificato 0 sarà comunque restituito 1 al suo posto.
In sostanza l'esecuzione di \func{longjmp} è analoga a quella di una
-istruzione \instruction{return}, solo che invece di ritornare alla riga
+istruzione \instr{return}, solo che invece di ritornare alla riga
successiva della funzione chiamante, il programma in questo caso ritorna alla
posizione della relativa \func{setjmp}. L'altra differenza fondamentale con
-\instruction{return} è che il ritorno può essere effettuato anche attraverso
+\instr{return} è che il ritorno può essere effettuato anche attraverso
diversi livelli di funzioni annidate.
L'implementazione di queste funzioni comporta alcune restrizioni dato che esse
In generale, dato che l'unica differenza fra la chiamata diretta e quella
ottenuta nell'uscita con un \func{longjmp} è costituita dal valore di ritorno
di \func{setjmp}, pertanto quest'ultima viene usualmente chiamata all'interno
-di un una istruzione \instruction{if} che permetta di distinguere i due casi.
+di un una istruzione \instr{if} che permetta di distinguere i due casi.
Uno dei punti critici dei salti non-locali è quello del valore delle
variabili, ed in particolare quello delle variabili automatiche della funzione
a cui si ritorna. In generale le variabili globali e statiche mantengono i
valori che avevano al momento della chiamata di \func{longjmp}, ma quelli
-delle variabili automatiche (o di quelle dichiarate \direct{register}) sono in
+delle variabili automatiche (o di quelle dichiarate \dirct{register}) sono in
genere indeterminati.
Quello che succede infatti è che i valori delle variabili che sono tenute in
\index{salto~non-locale|)}
+% TODO trattare qui le restartable sequences (vedi
+% https://lwn.net/Articles/664645/ e https://lwn.net/Articles/650333/) se e
+% quando saranno introdotte
+
\subsection{La \textit{endianness}}
\label{sec:endianness}