Quando un programma viene lanciato il kernel esegue un'opportuna routine di
avvio, usando il programma \cmd{ld-linux.so}. Questo programma prima carica
-le librerie condivise che servono al programma, poi effettua il link 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 \textit{linkati} 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}.
+le librerie condivise che servono al programma, poi effettua il collegamento
+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
+alcune variabili di ambiente e dal contenuto di \file{/etc/ld.so.conf}. I
+dettagli sono riportati nella man page 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
si suppone iniziare l'esecuzione; in ogni caso senza questa funzione lo stesso
-\textit{linker} darebbe luogo ad errori.
-
-Lo standard ISO C specifica che la funzione \func{main} può non avere
-argomenti o prendere due argomenti che rappresentano gli argomenti passati da
-linea di comando, in sostanza un prototipo che va sempre bene è il seguente:
+\textit{linker} (ci chiama così il programma che effettua i collegamenti di
+cui sopra) darebbe luogo ad errori. Lo standard ISO C specifica che la
+funzione \func{main} può non avere argomenti o prendere due argomenti che
+rappresentano gli argomenti passati da linea di comando, in sostanza un
+prototipo che va sempre bene è il seguente:
\includecodesnip{listati/main_def.c}
In realtà nei sistemi Unix esiste un'altro modo per definire la funzione
\func{main}, che prevede la presenza di un terzo argomento, \code{char
- *envp[]}, che fornisce l'\textsl{ambiente} (vedi sez.~\ref{sec:proc_environ})
-del programma; questa forma però non è prevista dallo standard POSIX.1 per cui
-se si vogliono scrivere programmi portabili è meglio evitarla.
+ *envp[]}, che fornisce (vedi sez.~\ref{sec:proc_environ})
+l'\textsl{ambiente} del programma; questa forma però non è prevista dallo
+standard POSIX.1 per cui se si vogliono scrivere programmi portabili è meglio
+evitarla.
\subsection{Come chiudere un programma}
La funzione chiude tutti i file descriptor appartenenti al processo (si tenga
presente che questo non comporta il salvataggio dei dati bufferizzati degli
-stream), fa sì che ogni figlio del processo sia ereditato da \cmd{init} (vedi
+stream), fa sì che ogni figlio del processo sia adottato da \cmd{init} (vedi
cap.~\ref{cha:process_handling}), manda un segnale \const{SIGCHLD} al processo
padre (vedi sez.~\ref{sec:sig_job_control}) ed infine ritorna lo stato di
uscita specificato in \param{status} che può essere raccolto usando la
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.}
+ è 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
puntatori a \val{NULL}).\footnote{si ricordi che questo vale solo per le
variabili che vanno nel segmento dati, e non è affatto vero in generale.}
- Storicamente questo segmento viene chiamato BSS (da \textit{block started by
- symbol}). La sua dimensione è fissa.
+ 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
\begin{figure}[htb]
\centering
- \includegraphics[height=12cm]{img/memory_layout}
+ \includegraphics[height=11cm]{img/memory_layout}
\caption{Disposizione tipica dei segmenti di memoria di un processo.}
\label{fig:proc_mem_layout}
\end{figure}
specializzata per il debugging). Esistono varie librerie che forniscono dei
sostituti opportuni delle routine di allocazione in grado, senza neanche
ricompilare il programma,\footnote{esempi sono \textit{Dmalloc}
- \href{http://dmalloc.com/}{http://dmalloc.com/} di Gray Watson ed
+ \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.
-
-\subsection{La funzione \func{alloca}}
-\label{sec:proc_mem_alloca}
+\subsection{Le funzioni \func{alloca}, \func{brk} e \func{sbrk}}
+\label{sec:proc_mem_sbrk_alloca}
Una possibile alternativa all'uso di \func{malloc}, che non soffre dei
problemi di \textit{memory leak}\index{\textit{memory~leak}} descritti in
cui torneremo in sez.~\ref{sec:proc_auto_var}.
-\subsection{Le funzioni \func{brk} e \func{sbrk}}
-\label{sec:proc_mem_sbrk}
-
Queste due funzioni 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
\begin{figure}[htb]
\centering
- \includegraphics[width=11cm]{img/argv_argc}
+ \includegraphics[width=13cm]{img/argv_argc}
\caption{Esempio dei valori di \param{argv} e \param{argc} generati nella
scansione di una riga di comando.}
\label{fig:proc_argv_argc}
In generale un programma Unix riceve da linea di comando sia gli argomenti che
le opzioni, queste ultime sono standardizzate per essere riconosciute come
tali: un elemento di \param{argv} che inizia con il carattere \texttt{'-'} e
-che non sia un singolo \texttt{'-'} o un \texttt{'--'} viene considerato
+che non sia un singolo \texttt{'-'} o un \texttt{'-{}-'} viene considerato
un'opzione. In genere le opzioni sono costituite da una lettera singola
(preceduta dal carattere \cmd{'-'}) e possono avere o no un parametro
associato; un comando tipico può essere quello mostrato in
dichiarata in \param{optstring} viene ritornato il carattere \texttt{'?'}
mentre se un opzione che lo richiede non è seguita da un parametro viene
ritornato il carattere \texttt{':'}, infine se viene incontrato il valore
-\texttt{'--'} la scansione viene considerata conclusa, anche se vi sono altri
+\texttt{'-{}-'} la scansione viene considerata conclusa, anche se vi sono altri
elementi di \param{argv} che cominciano con il carattere \texttt{'-'}.
\begin{figure}[htb]
fig.~\ref{fig:proc_envirno_list}.
\begin{figure}[htb]
\centering
- \includegraphics[width=11cm]{img/environ_var}
+ \includegraphics[width=13cm]{img/environ_var}
\caption{Esempio di lista delle variabili di ambiente.}
\label{fig:proc_envirno_list}
\end{figure}
numero fisso di argomenti per una funzione. Lo standard ISO C prevede nella
sua sintassi la possibilità di definire delle \textit{variadic
function}\index{variadic} che abbiano un numero variabile di argomenti,
-attraverso l'uso della \textit{ellipsis} \code{...} nella dichiarazione della
-funzione; ma non provvede a livello di linguaggio alcun meccanismo con cui
-dette funzioni possono accedere ai loro argomenti.
-
-L'accesso viene invece realizzato dalle librerie standard che provvedono gli
-strumenti adeguati. L'uso delle \textit{variadic function} prevede tre punti:
-\begin{itemize*}
+attraverso l'uso nella dichiarazione della funzione dello speciale costrutto
+``\texttt{...}'', che viene chiamato \textit{ellipsis}.
+
+Lo standard però non provvede a livello di linguaggio alcun meccanismo con cui
+dette funzioni possono accedere ai loro argomenti. L'accesso viene pertanto
+realizzato a livello delle librerie standard del C che provvedono gli
+strumenti adeguati. L'uso di una \textit{variadic function} prevede quindi
+tre punti:
+\begin{itemize}
\item \textsl{Dichiarare} la funzione come \textit{variadic} usando un
prototipo che contenga una \textit{ellipsis}.
-\item \textsl{Definire} la funzione come \textit{variadic} usando lo stesso
+\item \textsl{Definire} la funzione come \textit{variadic} usando la stessa
\textit{ellipsis}, ed utilizzare le apposite macro che consentono la
gestione di un numero variabile di argomenti.
-\item \textsl{Chiamare} la funzione specificando prima gli argomenti fissi, e
- a seguire gli addizionali.
-\end{itemize*}
+\item \textsl{Invocare} la funzione specificando prima gli argomenti fissi, ed
+ a seguire quelli addizionali.
+\end{itemize}
Lo standard ISO C prevede che una \textit{variadic function}\index{variadic}
abbia sempre almeno un argomento fisso; prima di effettuare la dichiarazione
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:
-\begin{enumerate*}
+\begin{enumerate}
\item Inizializzare un puntatore alla lista degli argomenti di tipo
\macro{va\_list} attraverso la macro \macro{va\_start}.
\item Accedere ai vari argomenti opzionali con chiamate successive alla macro
il secondo e così via.
\item Dichiarare la conclusione dell'estrazione degli argomenti invocando la
macro \macro{va\_end}.
-\end{enumerate*}
+\end{enumerate}
in generale è perfettamente legittimo richiedere meno argomenti di quelli che
potrebbero essere stati effettivamente forniti, e nella esecuzione delle
\macro{va\_arg} ci si può fermare in qualunque momento ed i restanti argomenti
\index{salto~non-locale|(}
-Il C però non consente di effettuare un salto ad
-una etichetta definita in un'altra funzione, per cui se l'errore avviene in
-una funzione, e la sua gestione ordinaria è in un'altra, occorre usare quello
-che viene chiamato un \textsl{salto non-locale}. Il caso classico in cui si
-ha questa necessità, citato sia da \cite{APUE} che da \cite{glibc}, è quello
-di un programma nel cui corpo principale vengono letti dei dati in ingresso
-sui quali viene eseguita, tramite una serie di funzioni di analisi, una
-scansione dei contenuti da si ottengono le indicazioni per l'esecuzione delle
-opportune operazioni.
+Il C però non consente di effettuare un salto ad una etichetta definita in
+un'altra funzione, per cui se l'errore avviene in una funzione, e la sua
+gestione ordinaria è in un'altra, occorre usare quello che viene chiamato un
+\textsl{salto non-locale}. Il caso classico in cui si ha questa necessità,
+citato sia in \cite{APUE} che in \cite{glibc}, è quello di un programma nel
+cui corpo principale vengono letti dei dati in ingresso sui quali viene
+eseguita, tramite una serie di funzioni di analisi, una scansione dei
+contenuti, da cui si ottengono le indicazioni per l'esecuzione di opportune
+operazioni.
Dato che l'analisi può risultare molto complessa, ed opportunamente suddivisa
in fasi diverse, la rilevazione di un errore nei dati in ingresso può accadere
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}).
+ o di iterazione (come \code{if}, \code{switch} o \code{while});
\item come operando per un operatore di uguaglianza o confronto in una
espressione di controllo di un comando condizionale, di selezione o di
- iterazione.
+ iterazione;
\item come operando per l'operatore di negazione (\code{!}) in una espressione
di controllo di un comando condizionale, di selezione o di iterazione.
\item come espressione a sé stante.