X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=process.tex;h=e67ae82e4e1acc25228e2846493e383b3a0d7610;hp=0dbe225bc0f6812388eaee1dce8249cda342e60b;hb=388493a5b44babce8434148b87562aea0f046db7;hpb=b93afedb7d7b01ba1f0b5ea4caaa281f38cb8e6d diff --git a/process.tex b/process.tex index 0dbe225..e67ae82 100644 --- a/process.tex +++ b/process.tex @@ -1,6 +1,6 @@ %% process.tex %% -%% Copyright (C) 2000-2004 Simone Piccardi. Permission is granted to +%% Copyright (C) 2000-2005 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", @@ -43,29 +43,30 @@ tutti gli altri.\footnote{questo non 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 parametro, \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. +\func{main}, che prevede la presenza di un terzo argomento, \code{char + *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} @@ -151,7 +152,7 @@ non vengono salvati e le eventuali funzioni registrate con \func{atexit} e 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 @@ -265,7 +266,7 @@ 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.} + è 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 @@ -374,8 +375,8 @@ seguenti segmenti: 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 @@ -401,7 +402,7 @@ seguenti segmenti: \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} @@ -434,10 +435,10 @@ una funzione e per le sue variabili locali (le cosiddette \textsl{variabili per queste variabili viene allocato nello stack quando viene eseguita la funzione e liberato quando si esce dalla medesima. -Esiste però un terzo tipo di allocazione, l'\textsl{allocazione dinamica della - memoria}, che non è prevista direttamente all'interno del linguaggio C, ma -che è necessaria quando il quantitativo di memoria che serve è determinabile -solo durante il corso dell'esecuzione del programma. +Esiste però un terzo tipo di allocazione, l'\textsl{allocazione dinamica} +della memoria, che non è prevista direttamente all'interno del linguaggio C, +ma che è necessaria quando il quantitativo di memoria che serve è +determinabile solo durante il corso dell'esecuzione del programma. Il C non consente di usare variabili allocate dinamicamente, non è possibile cioè definire in fase di programmazione una variabile le cui dimensioni @@ -501,7 +502,7 @@ quale si effettua l'allocazione. La memoria allocata dinamicamente deve essere esplicitamente rilasciata usando \func{free}\footnote{le glibc provvedono anche una funzione \func{cfree} definita per compatibilità con SunOS, che è deprecata.} una volta che non -sia più necessaria. Questa funzione vuole come parametro un puntatore +sia più necessaria. Questa funzione vuole come argomento un puntatore restituito da una precedente chiamata a una qualunque delle funzioni di allocazione che non sia già stato liberato da un'altra chiamata a \func{free}, in caso contrario il comportamento della funzione è indefinito. @@ -533,7 +534,7 @@ Un errore abbastanza frequente (specie se si ha a che fare con vettori di puntatori) è quello di chiamare \func{free} più di una volta sullo stesso puntatore; per evitare questo problema una soluzione di ripiego è quella di assegnare sempre a \val{NULL} ogni puntatore liberato con \func{free}, dato -che, quando il parametro è un puntatore nullo, \func{free} non esegue nessuna +che, quando l'argomento è un puntatore nullo, \func{free} non esegue nessuna operazione. Le \acr{glibc} hanno un'implementazione delle routine di allocazione che è @@ -603,14 +604,13 @@ funzioni di libreria una propria versione (che pu 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 @@ -666,9 +666,6 @@ Questo 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 @@ -902,16 +899,16 @@ di ambiente \cmd{IFS}. \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} \end{figure} Nella scansione viene costruito il vettore di puntatori \param{argv} inserendo -in successione il puntatore alla stringa costituente l'$n$-simo parametro; la +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 parametro è sempre il nome del programma; un esempio di +questo modo il primo argomento è sempre il nome del programma; un esempio di questo meccanismo è mostrato in fig.~\ref{fig:proc_argv_argc}. @@ -921,7 +918,7 @@ questo meccanismo 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 @@ -960,7 +957,7 @@ che indica che non ci sono pi 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] @@ -1020,11 +1017,11 @@ effettua il riordinamento del vettore \param{argv}. \label{sec:proc_opt_extended} Un'estensione di questo schema è costituito dalle cosiddette -\textit{long-options} espresse nella forma \cmd{--option=parameter}, anche la -gestione di queste ultime è stata standardizzata attraverso l'uso di una +\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: da finire). +(NdA: questa parte verrà inserita in seguito). \subsection{Le variabili di ambiente} @@ -1050,7 +1047,7 @@ pi 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} @@ -1074,7 +1071,7 @@ delle relative chiamate (si veda sez.~\ref{sec:proc_exec}). La shell ad esempio ne usa molte per il suo funzionamento (come \texttt{PATH} per la ricerca dei comandi, o \texttt{IFS} per la scansione degli argomenti), -e alcune di esse (come \texttt{HOME}, \texttt{USER}, etc.) sono definite al +e alcune di esse (come \texttt{HOME}, \texttt{USER}, ecc.) sono definite al login (per i dettagli si veda sez.~\ref{sec:sess_login}). In genere è cura dell'amministratore definire le opportune variabili di ambiente in uno script di avvio. Alcune servono poi come riferimento generico per molti programmi @@ -1199,7 +1196,7 @@ separatamente nome e valore della variabile di ambiente, inoltre il valore di variabile esista già, sovrascrivendola se diverso da zero, lasciandola immutata se uguale a zero. -La seconda funzione prende come parametro una stringa analoga quella +La seconda funzione prende come argomento una stringa analoga quella restituita da \func{getenv}, e sempre nella forma \code{NOME=valore}. Se la variabile specificata non esiste la stringa sarà aggiunta all'ambiente, se invece esiste il suo valore sarà impostato a quello specificato da @@ -1273,7 +1270,7 @@ che viene passato alla subroutine variabile, copia che la subroutine potrà modificare a piacere, senza che il valore originale nella routine chiamante venga toccato. In questo modo non occorre preoccuparsi di eventuali effetti delle operazioni della subroutine -sulla variabile passata come parametro. +sulla variabile passata come argomento. Questo però va inteso nella maniera corretta. Il passaggio \textit{by value} vale per qualunque variabile, puntatori compresi; quando però in una @@ -1308,21 +1305,23 @@ Come vedremo nei capitoli successivi, non sempre 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 @@ -1332,8 +1331,8 @@ sez.~\ref{sec:proc_exec}: \includecodesnip{listati/exec_sample.c} in questo caso la funzione prende due argomenti fissi ed un numero variabile di altri argomenti (che verranno a costituire gli elementi successivi al primo -del vettore \param{argv} passato al nuovo processo). Lo standard ISO C richiede -inoltre che l'ultimo degli argomenti fissi sia di tipo +del vettore \param{argv} passato al nuovo processo). Lo standard ISO C +richiede inoltre che l'ultimo degli argomenti fissi sia di tipo \textit{self-promoting}\footnote{il linguaggio C prevede che quando si mescolano vari tipi di dati, alcuni di essi possano essere \textsl{promossi} per compatibilità; ad esempio i tipi \ctyp{float} vengono convertiti @@ -1341,7 +1340,7 @@ inoltre che l'ultimo degli argomenti fissi sia di tipo \ctyp{int}. Un tipo \textit{self-promoting} è un tipo che verrebbe promosso a sé stesso.} il che esclude vettori, puntatori a funzioni e interi di tipo \ctyp{char} o \ctyp{short} (con segno o meno). Una restrizione ulteriore di -alcuni compilatori è di non dichiarare l'ultimo parametro fisso come +alcuni compilatori è di non dichiarare l'ultimo argomento fisso come \direct{register}. Una volta dichiarata la funzione il secondo passo è accedere ai vari argomenti @@ -1352,7 +1351,7 @@ L'unica modalit 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 @@ -1360,7 +1359,7 @@ macro; la procedura da seguire 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 @@ -1378,7 +1377,7 @@ Le definizioni delle tre macro sono le seguenti: l'ultimo degli argomenti fissi. \funcdecl{type va\_arg(va\_list ap, type)} Restituisce il valore del - successivo parametro opzionale, modificando opportunamente \param{ap}; la + successivo argomento opzionale, modificando opportunamente \param{ap}; la macro richiede che si specifichi il tipo dell'argomento attraverso il parametro \param{type} che deve essere il nome del tipo dell'argomento in questione. Il tipo deve essere \textit{self-promoting}. @@ -1393,7 +1392,7 @@ e ciascuno potr Dopo l'uso di \macro{va\_end} la variabile \param{ap} diventa indefinita e successive chiamate a \macro{va\_arg} non funzioneranno. Si avranno risultati indefiniti anche chiamando \macro{va\_arg} specificando un tipo che non -corrisponde a quello del parametro. +corrisponde a quello dell'argomento. Un altro limite delle macro è che i passi 1) e 3) devono essere eseguiti nel corpo principale della funzione, il passo 2) invece può essere eseguito anche @@ -1445,7 +1444,7 @@ stabilire quanti sono gli argomenti passati effettivamente in una chiamata. Esistono varie modalità per affrontare questo problema; una delle più immediate è quella di specificare il numero degli argomenti opzionali come uno -degli argomenti fissi. Una variazione di questo metodo è l'uso di un parametro +degli argomenti fissi. Una variazione di questo metodo è l'uso di un argomento per specificare anche il tipo degli argomenti (come fa la stringa di formato per \func{printf}). @@ -1486,15 +1485,15 @@ programma: quello dell'uscita in caso di errore. \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 @@ -1575,10 +1574,10 @@ pertanto non si pu 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.